• Упрощается реализация схем защиты памяти, то есть записи в таблице страниц могут быть помечены, чтобы показать, что содержимое соответствующей страницы защищено от всего, кроме чтения, записи, выполнения или некоторого сочетания допустимых действий. Когда страницы оперативной памяти совместно применяются несколькими процессами, можно указать, что у памяти есть защита от каждого процесса. Например, у одного процесса может быть доступ только к чтению страницы, а у другого — как к чтению, так и к записи.
• Программистам и таким инструментам, как компилятор и компоновщик, не нужно знать о физическом размещении программы в оперативной памяти.
• Программа загружается и запускается быстрее, поскольку в памяти требуется разместить только ее часть. Кроме того, объем памяти для среды выполнения процесса (то есть виртуальный размер) может превышать емкость оперативной памяти.
И еще одно последнее преимущество, получаемое за счет управления виртуальной памятью, заключается в том, что факт задействования каждым процессом меньшего объема оперативной памяти позволяет одновременно содержать в ней большее количество процессов. Как правило, это приводит к более эффективному использованию центрального процессора, поскольку увеличивает вероятность того, что в любой момент времени найдется хотя бы один процесс, который может быть выполнен центральным процессором.
По мере вызова функций и возврата из них стек расширяется и сжимается. В Linux на архитектуре x86-32 (и в большинстве других реализаций Linux и UNIX) стек располагается в верхней части памяти и растет вниз (по направлению к куче). Текущая вершина стека отслеживается в специально предназначенном для этого регистре —
Хотя стек растет вниз, мы все равно называем растущий край стека вершиной, поскольку, абстрактно говоря, он таковым и является. Фактическое направление роста относится к подробностям аппаратной реализации. В одной из реализаций Linux, HP PA-RISC, используется стек, растущий вверх.
С точки зрения виртуальной памяти, при выделении стекового фрейма сегмент стека увеличивается в размере, но в большинстве реализаций его размер после высвобождения фреймов не уменьшается (память просто повторно используется при выделении новых стековых фреймов). Когда говорится о расширении и сжатии сегмента стека, речь идет о логической перспективе добавляемых в стек и удаляемых из него фреймов.
Иногда применяется выражение
Каждый фрейм пользовательского стека содержит следующую информацию.
•
•
Поскольку функции способны вызывать друг друга, в стеке может быть несколько фреймов. (Если функция рекурсивно вызывает саму себя, то для этой функции в стеке будет несколько фреймов.) Если вспомнить листинг 6.1, то в ходе выполнения функции square() в стеке будут содержаться фреймы, показанные на рис. 6.3.
Рис. 6.3.