
6.1.4. Размер страниц и фрагментация
Обычно программа не занимает целое число страниц. На последней ее странице остается неиспользованное пространство. С другой стороны, при работе с динамической памятью могут запрашиваться блоки различной длины, что также не способствует плотному заполнению памяти. Эта проблема называется внутренней фрагментацией (неиспользуемое пространство является внутренним по отношению к странице).
При размере страницы в n байтов среднее неиспользованное пространство в последних страницах составляет n/2 байтов. С этой точки зрения выгоднее использовать страницы небольшого размера. Более того, рабочее множество будет состоять из большего количества страниц. В этом случае оно может охватить большее количество несвязанных областей, что снижает вероятность пробуксовки.
С другой стороны, при маленьком размере потребуется много страниц и большая таблица страниц. Этот факт увеличивает расходы ресурсов компьютера. Кроме того, при большом количестве страниц увеличивается частота обращений к диску.
Таким образом, существует проблема компромисса при выборе размера страницы виртуальной памяти.
6.1.5. Сегментация
До сих пор речь шла об одномерной виртуальной памяти, в которой виртуальные адреса имеют линейную структуру. Однако по ряду причин удобнее использовать два или более отдельных виртуальных адресных пространств. Например, компилятор может иметь несколько временных таблиц, которые создаются в процессе компиляции и непредсказуемо меняют свою величину. Если создавать их в смежных областях, то переполнение одной может вызывать перераспределение большинства из них. Наличие нескольких адресных пространств позволяет эффективнее использовать память. С другой стороны, удобно помещать программу и данные в различные адресные пространства, т. к. страницы области программы обычно не модифицируются и их не нужно при удалении записывать на диск. Применение нескольких адресных пространств помогает также реализовать многозадачность.
Несколько независимых виртуальных адресных пространств называются сегментами. Каждый сегмент состоит из линейной последовательности адресов. Длина каждого сегмента может быть произвольной. Более того, длина сегмента может меняться во время выполнения программы. Разные сегменты могут увеличиваться или уменьшаться не влияя друг на друга. Так если стеку в определенном сегменте понадобится больше адресного пространства, он может получить его без проблем. Таким образом, память становится двумерной. Чтобы определить адрес, программа должна выдавать номер сегмента и адрес внутри сегмента.
В отличие от страницы, сегмент является логическим элементом, о котором программист знает и может использовать (по крайней мере, на ассемблере). Дополнительный сегмент может содержать процедуру, массив, стек или ряд скалярных переменных, обычно в него входит только один тип данных.
Если каждая процедура занимает отдельный сегмент, в котором первый адрес = 0, то компоновка отдельно компилируемых процедур существенно упрощается. При изменении и перекомпиляции процедур другие менять не нужно даже на этапе редактирования связей, т.к. точки входа не меняются. Этот же принцип облегчает разделение общих процедур или данных между несколькими параллельными программами.
Разные сегменты виртуальной памяти могут иметь разные виды защиты. Например, сегмент с процедурой можно определить как “только для выполнения”, запретив тем самым не только запись, но и считывание из него. Для массива данных разрешается только чтение и запись, но не выполнение и т. д. Такая защита помогает обнаружить ошибки в программе.