Реклама:

До сих пор мы говорили об одномерной виртуальной памяти, в которой виртуальные адреса следуют один за другим от 0 до какого-то максимального адреса. Однако по многим причинам гораздо удобнее использовать два или несколько отдельных виртуальных адресных пространств. Например, компилятор может иметь несколько структур, которые создаются в процессе компиляции; такими структурами могут быть:

♦ символьная таблица с именами и атрибутами переменных;

♦ исходный текст для распечатки;

♦ таблица со всеми использующимися целочисленными константами и константами с плавающей точкой;

♦ дерево синтаксического разбора программы;

♦ стек, используемый для вызова процедур в компиляторе.

Каждая из первых четырех структур постоянно растет в процессе компиляции. Размер последней структуры меняется совершенно непредсказуемо. В одномерной памяти эти пять структур пришлось бы разместить в виртуальном адресном пространстве в виде смежных областей, как показано на рис. 6.6.

Посмотрим, что произойдет, если программа содержит очень большое число переменных. Область адресного пространства, предназначенная для таблицы символов, может переполниться, даже если в других таблицах полно свободного места. Компилятор, конечно, может сообщить, что он не способен продолжать работу из-за большого количества переменных, но можно без этого и обойтись, поскольку в других таблицах много свободного места.

Сегментация

Рис. 6.6. Если в одномерном адресном пространстве размер структур постоянно растет, одна из них может "врезаться" в другую

Компилятор может забирать свободное пространство у одних структур и передавать другим, но это будет напоминать управление оверлеями вручную - некоторое неудобство в лучшем случае и долгая нудная работа в худшем.

На самом деле нужно просто освободить программиста от необходимости думать о расширении и сокращении структур, подобно тому, как виртуальная память позволяет забыть о разбиении программы на оверлеи.

Для этого нужно создать множество абсолютно независимых адресных пространств, которые называются сегментами. Каждый сегмент состоит из линейной последовательности адресов от 0 до какого-либо допустимого максимума. Разные сегменты могут иметь разную длину (обычно так и бывает). Более того, длина сегмента может меняться во время выполнения программы. Длина стекового сегмента может увеличиваться всякий раз, когда что-либо помещается в стек, и уменьшаться, когда что-либо выталкивается из стека.

Так как каждый сегмент образует отдельное адресное пространство, разные сегменты могут увеличиваться или уменьшаться независимо друг от друга и не влияя друг на друга. Если стеку в определенном сегменте потребуется больше адресного пространства (чтобы стек мог расти), он может получить его, поскольку его адресному пространству больше не во что "врезаться". Естественно, сегмент может переполниться, но это происходит редко, поскольку сегменты очень большие. Чтобы задать адрес в двухмерной памяти, программа должна указать номер сегмента и адрес внутри сегмента. Сегментированная память изображена на рис. 6.7.

Сегментация

Рис. 6.7. Сегментированная память позволяет менять размер каждой структуры независимо от других

Подчеркнем, что сегмент является логическим элементом, о котором программист знает и который он использует. Сегмент может содержать процедуру, массив, стек или ряд скалярных переменных, но обычно в него входит только один тип данных.

Сегментированная память имеет и другие преимущества, помимо упрощения работы со структурами данных, которые постоянно меняются в размерах. Если каждая процедура занимает отдельный сегмент, в котором первый адрес - это адрес 0, то сборка процедур, скомпилированных раздельно, значительно упрощается. Когда все процедуры программы скомпилированы и собраны, при вызове процедуры из сегмента п для обращения к слову 0 будет использоваться адрес (и, 0).

Если процедура в сегменте п впоследствии будет изменена и перекомпилирована, то другие процедуры менять не потребуется (поскольку их начальные адреса не изменятся), даже если новая версия окажется больше по размеру, чем предыдущая. В одномерной памяти процедуры обычно располагаются друг за другом, и между ними нет свободного адресного пространства. Следовательно, изменение размера одной процедуры может повлиять на начальные адреса других процедур. Это, в свою очередь, потребует изменения всех других процедур, которые вызывают любую из указанных. Если в программу включено множество процедур, переделка оказывается весьма трудоемкой.

Сегментация облегчает совместное использование процедур или данных несколькими программами. Если компьютер содержит несколько программ, работающих параллельно (это может быть реальный или моделируемый параллелизм), и все эти программы вызывают одни и те же процедуры, снабжать каждую программу отдельными копиями процедур расточительно для памяти. Если же сделать каждую процедуру отдельным сегментом, их легко можно будет использовать совместно, что исключит необходимость создавать физические копии каждой разделяемой процедуры. В результате мы сэкономим память.

Поскольку каждый сегмент являет собой логический объект (например, процедуру, массив или стек), о существовании которого знает программист, разные сегменты можно защищать по-разному. Например, сегменту с процедурой можно назначить атрибут "только для выполнения", запретив тем самым считывание из него и запись в него. Для массива с плавающей точкой можно разрешить только чтение и запись, но не выполнение и т. д. Такая защита часто помогает выявлять программные ошибки.

Нужно понимать, почему защита имеет смысл только для сегментированной памяти и не имеет никакого смысла для одномерной (линейной) памяти. Обычно в сегменте не могут находиться одновременно процедура и стек (только что-нибудь одно). Поскольку каждый сегмент содержит объект только одного типа, он может использовать защиту, подходящую для этого типа. Страничная организация памяти и сегментация сравниваются в табл. 6.1.

Таблица 6-1- Сравнение страничной организации памяти и сегментации

Свойство

Страничная организация памяти

Сегментация

Необходимость учета программистом

Нет

Да

Количество линейных адресных пространств

Много

Возможность увеличения памяти для виртуального адресного пространств

Да

Да

Простота управления структурами переменного размера

Нет

Да

Назначение технологии

Имитация памяти большого размера

Предоставление нескольких адресных пространств

Содержимое страницы в каком-то смысле случайно. Программист может ничего не знать о страничной организации памяти. В принципе можно поместить несколько битов в каждый элемент таблицы страниц для доступа к нему, но чтобы использовать эту особенность, программисту придется следить за границами страницы в адресном пространстве. Но ведь механизм разбиения памяти на страницы был придуман именно для устранения подобных трудностей. Что же касается сегментации, то поскольку у пользователя создается иллюзия, что все сегменты постоянно находятся в основной памяти, к ним можно обращаться и не следить при этом за оверлеями.

Размер страниц и фрагментация || Оглавление || Реализация сегментации