Прежде всего мы должны ввести новое понятие: виртуальное адресное пространство. Виртуальное адресное пространство — это максимально доступное приложению адресное пространство. Объём виртуального адресного пространства зависит от архитектуры компьютера и операционной системы. Он зависит от архитектуры компьютера, так как именно архитектура определяет, сколько бит используется для адресации. Он также зависит от операционной системы, так как в зависимости от реализации операционная система может накладывать дополнительные ограничения, помимо ограничений архитектуры.
Прилагательное «виртуальное» применительно к виртуальному адресному пространству означает, что это общее число доступных приложению уникально адресуемых ячеек памяти, но не общий объём памяти, установленной в компьютере, или выделенной в конкретный момент времени данному приложению.
В случае с нашим приложением объём его виртуального адресного пространства равен 15000 байт.
Для реализации виртуальной памяти в компьютере должен быть специальный аппаратный механизм управления памятью. Часто этот механизм называют устройством управления памятью (Memory Management Unit, MMU). Если MMU отсутствует, при обращении процессора к памяти реальный адрес в памяти никогда не меняется — адрес 123 всегда соответствует одной физической ячейке ОЗУ.
Однако с MMU адреса проходят этап преобразования, прежде чем произойдёт обращение к памяти. Это значит, что адресу памяти 123 в одном случае может соответствовать физический адрес 82043, а в другом случае — физический адрес 20468. Но если сопоставлять виртуальные адреса физическим для каждого из миллиардов байт памяти, издержки будут слишком велики. Вместо этого, MMU делит ОЗУ на страницы — непрерывные блоки памяти заданного размера, которые рассматриваются MMU как одно целое.
Может показаться, что введение страниц и преобразования адресов — необязательный и непонятный дополнительный шаг. Однако он очень важен для реализации виртуальной памяти. Поэтому давайте рассмотрим следующую ситуацию.
Вернувшись к нашему гипотетическому приложению с виртуальным адресным пространством 15000 байт, предположим, что первая инструкция обращается к данным по адресу 12374. Также предположим, что в нашем компьютере всего 12288 байт физической памяти. Что произойдёт, если процессор попытается обратиться к адресу 12374?
Произойдёт так называемая ошибка страницы.
4.4.1. Ошибки страницы
Ошибка страницы — это последовательность событий, происходящих, когда программа пытается обращаться к данным (или коду) в своём адресном пространстве, которые в данный момент отсутствуют в ОЗУ. Операционная система может обработать ошибки страницы, каким-то образом загрузив запрашиваемые данные в память, что позволит программе продолжить работу, как если бы никакой ошибки не было.
В случае с нашим гипотетическим приложением, процессор сначала передаёт нужный адрес (12374) устройству MMU. Однако, MMU не может преобразовать этот адрес. Поэтому MMU прерывает процессор и вызывает программу, так называемый обработчик ошибки страницы. Затем обработчик ошибки страницы определяет, что нужно сделать для решения этой проблемы. Он может:
найти, где находится на диске запрошенная страница, и прочитать её (это обычно происходит в случае ошибки страницы с кодом)
определить, что запрошенная страница уже находится в ОЗУ (но выделена не текущему процессу), и подключить эту страницу, настроив MMU
указать на специальную страницу с одними нулями и выделить для процесса новую страницу, только если процесс когда-нибудь попытается записать в неё данные (этот приём называется копированием при записи и часто используется для страниц, изначально содержащих нули)
получить нужную страницу откуда-то ещё (это будет рассмотрено более подробно позже)
Тогда как первые три действия достаточно очевидны, последнее вовсе нет. Чтобы разобраться с ним, мы должны обсудить некоторые дополнительные темы.
4.4.2. Рабочее множество
Набор страниц физической памяти, в данный момент выделенных определённому процессу, называется рабочим множеством этого процесса. Число страниц в рабочем множестве может увеличиваться и уменьшаться, в зависимости от общей доступности страниц в системе в целом.
Рабочее множество процесса увеличивается при увеличении числа ошибок страницы, и уменьшается по мере того, как остаётся всё меньше свободных страниц. Чтобы память не была израсходована полностью, время от времени страницы должны исключаться из рабочих множеств процессов и становиться свободными, доступными для дальнейшего использования. Операционная система сжимает рабочие множества процессов:
записывая изменённые страницы в выделенную область устройства хранения (обычно эта область называется пространством подкачки).
помечая неизменённые страницы как свободные (записывать эти страницы на диск нет необходимости, так как они не менялись)
Чтобы определить подходящий размер рабочих множеств всех процессов, операционная система должна следить за использованием всех страниц. Таким образом операционная система определяет, какие страницы используются активно (и должны остаться в памяти), а какие — нет (и следовательно, могут быть удалены из памяти). Для того, чтобы определить, какие страницы лучше удалить из рабочих множеств процессов, чаще всего применяется некая разновидность алгоритма учёта последних использованных страниц.
4.4.3. Подкачка
Хотя подкачка (запись изменённых страниц в пространство подкачки и последующая их загрузка) — обычное явление при работе системы, подкачка может быть слишком активной. Слишком активная подкачка нежелательна, так как при этом может легко произойти, а затем снова и снова повторяться следующая ситуация:
Страницы процесса выгружаются в пространство подкачки
Этот процесс становится исполняемым и пытается обратиться к выгруженной странице
Происходит ошибка страницы и нужная страница загружается в память (при этом, вероятнее всего, вытесняя страницу другого процесса)
Чуть позже страница снова выгружается на диск
Если эта последовательность событий повторяется неоднократно, происходит перегрузка и это говорит о том, что для текущей нагрузки памяти не хватает. Такие перегрузки крайне негативно влияют на производительность, так как возникающая в такой ситуации нагрузка процессора и подсистемы ввода/вывода быстро превышает полезную нагрузку системы. В экстремальных случаях компьютер может вообще не выполнять полезную работу, расходуя все свои ресурсы на перемещение страниц в память и из памяти.