Виртуальное адресное пространство каждого процесса делится на части одинакового, фиксированного раздела, называемые виртуальными страницами.
Вся оперативная память машины также делится на части такого же размера, называемые физическими страницами (блоками, или кадрами, или фреймами). Размер страницы выбирается равным степени двойки: 512, 1024 и 4096 байт и т. д. Это позволяет упростить механизм преобразования адресов.
При создании процесса ОС загружает в оперативную память несколько его виртуальных страниц (начальные страницы кодового сегмента и сегмента данных). Копия всего виртуального адресного пространства процесса находится на диске. Смежные виртуальные страницы не обязательно располагаются в смежных физических страницах. Для каждого процесса операционная система создает таблицу страниц – информационную структуру, содержащую записи обо всех виртуальных страницах процесса. Кроме того, операционная система поддерживает единый список свободных, (то есть не занятых никаким процессом и доступных для размещения в них страниц) кадров.
Запись таблицы, называемая дескриптором страницы, включает следующую информацию:
ü Номер физической страницы, в которую загружена данная виртуальная страница;
ü Признак присутствия, устанавливаемый в единицу, если виртуальная страница находится в оперативной памяти;
ü Признак модификации страницы, который устанавливается в единицу всякий раз, когда производится запись по адресу, относящемуся к данной странице;
ü Признак обращения к странице, называемый также битом доступа, который устанавливается в единицу при каждом обращении по адресу, относящемуся к данной странице.
Информация из таблиц страниц используется для решения вопроса о необходимости перемещения той или иной страницы между памятью и диском, а также для преобразования виртуального адреса в физический. Сами таблицы страниц, также как и описываемые ими страницы, размещаются в оперативной памяти.
Адрес таблицы страниц включается в контекст соответствующего процесса. При активизации очередного процесса операционная система загружает адрес его таблицы страниц в специальный регистр процессора.
При каждом обращении к памяти
- выполняется поиск номера виртуальной страницы, содержащий требуемый адрес,
- затем по этому номеру определяется нужный элемент таблицы страниц,
- и из него извлекается описывающая страницу информация.
Далее анализируется признак присутствия, и, если данная виртуальная страница находится в оперативной памяти, то выполняется преобразование виртуального адреса в физический.
Если нужная виртуальная страница в данный момент выгружена на диск, то происходит так называемое страничное прерывание. Выполняющийся процесс переводится в состояние ожидания, и активизируется другой процесс из очереди процессов, находящихся в состоянии готовности. Параллельно программа обработки страничного прерывания находит на диске требуемую виртуальную страницу и пытается загрузить ее в оперативную память. Если в памяти имеется свободная физическая страница, то загрузка выполняется немедленно. Если же свободных страниц нет, то на основании принятой в данной системе стратегии замещения страниц решается вопрос о том, какую страницу следует выгрузить из оперативной памяти.
В данной ситуации может быть использовано много разных критериев выбора. Наиболее популярные из них следующие:
- дольше всего не использовавшаяся страница;
- первая попавшаяся страница;
- страница, к которой в последнее время было меньше всего обращений.
После того как выбрана страница, которая должна покинуть оперативную память, обнуляется ее бит присутствия и анализируется ее признак модификации. Если выталкиваемая страница за время последнего пребывания в оперативной памяти была модифицирована, то ее новая версия переписывается на диск. Если нет, то никакой записи на диск не производится, так как на диске уже имеется предыдущая копия этой виртуальной страницы. Физическая страница объявляется свободной.
Итак, в случае простой страничной организации основная память разделяется на множество небольших кадров одинакового размера. Каждый процесс разделяется на страницы того же размера, что и кадры; малые процессы требуют меньшего количества кадров, большие - большего. При загрузке процесса в память все его страницы загружаются в свободные кадры, и информация о размещении страниц заносится в соответствующую таблицу. Такой подход позволяет избежать множества присущих распределению памяти проблем.
|
|
| ||
| ||
| ||
Стр. 0, пр. 1 | ||
Стр. 0, пр. 2 | ||
Стр. 3, пр. 1 | ||
Стр. 5, пр. 2 | ||
... | ||
|
0 |
1 |
2 |
3 |
4 |
№ ср. с. | Упр. инф. | |
0 | 5 | |
1 | ВП | |
2 | ВП | |
3 | 10 | |
4 | 2 |
|
|
№ ср. с. | Упр. инф. | |
0 | 8 | |
1 | ВП | |
2 | ВП | |
3 | ВП | |
4 | ВП | |
5 | 11 |
0 |
1 |
2 |
3 |
4 |
5 |
|
Рис. 5. Страничное распределение памяти.
Сегментное распределение
Методы распределения памяти, при которых задаче уже может не предоставляться сплошная (непрерывная) область памяти, называют разрывными. Идея выделять память задаче не одной сплошной областью, а фрагментами позволяет уменьшить фрагментацию памяти, однако этот подход требует для своей реализации больше ресурсов, он намного сложнее.
Если задать адрес начала текущего фрагмента программы и величину смещения относительно этого начального адреса, то можно указать необходимую нам переменную или команду. Таким образом, виртуальный адрес можно представить состоящим из двух полей. Первое поле будет указывать на ту часть программы, к которой обращается процессор для определения местоположения этой части в памяти, а второе поле виртуального адреса позволит найти нужную нам ячейку относительно найденного адреса. программист может либо самостоятельно разбивать программу на фрагменты, либо можно автоматизировать эту задачу, возложив её на систему программирования.
Первым среди разрывных методов распределения памяти был сегментный.
Для этого метода программу необходимо разбивать на части и уже каждой такой части выделять физическую память. Естественным способом разбиения программы на части является разбиение её на логические элементы – так называемые сегменты. Каждый сегмент размещается в памяти как (до определенной степени) самостоятельная единица. Логически обращение к элементам программы в этом случае будет состоять из имени сегмента и смещения относительно начала этого сегмента.
Физически имя (или порядковый номер) сегмента будет соответствовать некоторому адресу, с которого этот сегмент начинается при его размещении в памяти, и смещение должно прибавляться к этому базовому адресу.
Преобразование имени сегмента в его порядковый номер осуществит система программирования. Для каждого сегмента система программирования указывает его объем. Он должен быть известен операционной системе, чтобы она могла выделять ему необходимый объём памяти. Операционная система будет размещать сегменты в памяти и для каждого сегмента она должна вести учёт о местонахождении этого сегмента. Вся информация о текущем размещении сегментов задачи в памяти обычно сводится в таблицу сегментов. Каждая задача имеет свою таблицу сегментов.
На рис. 6 проиллюстрировано обращение к ячейке, виртуальный адрес которой равен сегменту с номером 11 со смещением от начала этого сегмента, равным 612. Как мы видим, операционная система разместила данный сегмент в памяти, начиная с ячейки с номером 19700.
| |||
| |||
Рис. 6
При страничной организации виртуальное адресное пространство процесса делится механически на равные части. Это не позволяет дифференцировать способы доступа к разным частям программы (сегментам), а это свойство часто бывает очень полезным. Например, можно запретить обращаться с операциями записи и чтения в кодовый сегмент программы, а для сегмента данных разрешить только чтение. Кроме того, разбиение программы на «осмысленные» части делает принципиально возможным разделение одного сегмента несколькими процессами. Например, если два процесса используют одну и туже математическую подпрограмму, то в ОП может быть загружена только одна копия этой подпрограммы.
Рассмотрим, каким образом сегментное распределение памяти реализует эти возможности (Рис. 5).