Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Theory 2.Architecture _Unix.doc
Скачиваний:
4
Добавлен:
01.05.2025
Размер:
239 Кб
Скачать
☆

6.6. Управление памятью

Традиционно API Unix представляет сегментную модель памяти. Каждому процессу при создании выделяется три сегмента: сегмент кодов, сегмент данных и сегмент стека. Процесс может изменять размер выделенного ему сегмента, а также получать сегменты разделяемой памяти и управлять ими.

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

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

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

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

Список абсолютно свободных страниц, то есть страниц, не включенных в адресное пространство никакого процесса.

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

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

Рисунок 6.4 Логическая структура управления адресным пространством процесса

Представленная на рисунке 6.4 структура управления адресным пространством процесса является логической концепцией, реализация ее на разных аппаратных платформах может существенно различаться. Так, в Open Unix и в других клонах на платформе Intel-Pentium сегментная структура адресного пространства является лишь оболочкой, обеспечиваемой программным окружением, а не ОС. На самом же деле адресное пространство процесса здесь представляет собой просто массив страниц. Сегменты являются только группами страниц, а представляются для процесса в виде традиционных для Unix сегментов только модулями библиотеки системных вызовов.

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

Ранние версии Unix поддерживали две модели свопинга - подкачку страниц (описанную выше) и подкачку процессов. Вторая модель, исторически появившаяся первой, была ориентирована на сегментную модель динамической трансляции адресов в аппаратуре, но вытеснялся при этом весь процесс, всеми своими сегментами. Состояния процесса "приостановлен, вытеснен" и "готов, вытеснен" на рисунке 6.3. связаны именно с моделью подкачки процессов. При повсеместном внедрении аппаратных платформ с сегментно-страничной аппаратной трансляцией адресов произошел отказ от подкачки процессов и свопинг ограничился только страничным уровнем. Однако в дальнейшем подкачка процессов была совмещена с подкачкой страниц. Так, в Open Unix при нормальной загрузке свопинг осуществляется только на страничном уровне. Однако при существенной нехватке памяти процесс может быть вытеснен целиком, всеми своими страницами. Таким образом, состояния "приостановлен, вытеснен" и "готов, вытеснен" продолжают оставаться актуальными.

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

Современная ОС Unix обеспечивает также файлы, отображаемые в память. Системный вызов mmap возвращает адрес в виртуальном адресном пространстве процесса данных открытого файла. Семантика вызова mmap такова:

paddr=mmap(addr,len,prot,flags,fd,off);

где addr - "заказываемый" виртуальный адрес сегмента в адресном пространстве процесса (возвращаемое значение может и не совпадать с ним), len - размер сегмента, prot - возможности доступа, flags - управляющие флаги, fd - манипулятор файла или другого объекта, off - смещение в файле.

Задание смещения и размера отображаемой области дает возможность, если размер файла превышает доступный размер виртуальной памяти, отображать файл частями или создавать "плавающие окна" отображения. Механизм отображения в память применим не только к файлам на внешней памяти, но и к другим объектам, внешние имена которых находятся в пространстве имен файловой системы: таблицам, структурам, общим областям памяти и т.п. Однако отображаемые объекты обязательно должны быть объектами памяти - оперативной или внешней. Не могут быть отображаемыми файлами, например, терминалы или сетевые соединения.

Механизм отображения в память в Open Unix заменяет старые средства управления памятью. Хотя традиционные системные вызовы управления памятью здесь тоже сохраняются, но они обеспечиваются только библиотекой системных вызовов, которая преобразует их в отображение в память. Механизм отображения в память позволяет процессам также получать дополнительные частные сегменты в адресном пространстве процессе. Отображение в память "файла" с именем "/dev/zero" дает процессу частный сегмент запрошенного размера.

Выполнение системного вызова fork в традиционной ОС Unix подразумевает откладывание выделения для процесса-потомка отдельных частных сегментов. Вместо этого применяется политика "копирования при записи": два процесса - предок и потомок - разделяют один сегмент, но этот сегмент помечается как защищенный от записи. Пока ни один из процессов не изменяет содержимого сегмента, процессы используют один и тот же сегмент. Когда один из процессов пытается писать в сегмент, происходит исключение, обрабатывая которое ОС создает копию сегмента для процесса-потомка, и с этого момента каждый процесс использует свой собственный сегмент. В Open Unix политика "копирования при записи" реализуется на уровне страниц.

Динамическая компоновка в современных Unix в принципе идентична таковой во многих других современных ОС (OS/2, Windows 9x, Windows NT). Модули динамической компоновки называются здесь разделяемыми объектами (shared object). Они представляют собой программные модули, содержащие несколько входных точек. Библиотека разделяемых объектов, однако, содержат не один такой модуль, а целый набор их. При загрузке или при выполнении кодовый сегмент разделяемого объекта включается в адресное пространство процесса. Код разделяемого объекта совместно используется всеми процессами, но отображается в общем случае в разные участки виртуальной памяти разных процессов. Разделяемые объекты, таким образом, компилируются и компонуются так, чтобы они могли быть перемещаемыми в виртуальном адресном пространстве. Для переменных разделяемого объекта создается отдельная область для каждого процесса, использующего объект.