В существующих вычислительных системах наиболее часто в качестве виртуального ресурса реализуется память. Механизм поддержки виртуальной памяти появился впервые в МП Intel 80386 (1985 год). Познакомимся с принципами его действия.
Интерес к использованию виртуальной памяти появился вследствие того, что адресное пространство, доступное МП (4 Гбайт для 80386) намного превышало объем реального ЗУ, используемого в вычислительной системе. Получалось, что большая часть адресного пространства "пропадала" и возможности процессора использовались неэффективно.
Возникла идея: сделать так, чтобы для программы были доступны все 4 Гбайт памяти. В основу концепции виртуальной памяти было положено допущение о локальности данных. Оно предполагало, что данные, интенсивно используемые программой в некоторый момент времени, расположены в памяти компактно и занимают часть адресного пространства, которая может быть целиком отображена в реальную физическую память. Данные, расположенные в оставшемся адресном пространстве и не используемые в данный момент, могут находиться за пределами ЗУ, например, на жестком диске. Таким образом, виртуальная память состоит из двух частей — собственно физической памяти и "файла подкачки", расположенного на жестком диске, в который помещаются данные, соответствующие части адресного пространства, не отображаемого в данный момент в физическую память.
Принцип действия виртуальной памяти получался при этом достаточно прост. Данные, используемые активной в данный момент программой, размещались в физической памяти. Когда активной становилась другая программа, содержимое физической памяти копировалось на диск, а в физическую память с диска загружались данные, необходимые новой активной программе. Процедура "подкачки" данных с диска ("свопинг") была незаметной для прикладной программы, поэтому у нее создавалась иллюзия наличия реальной памяти большого объема.
Важно отметить, что механизм виртуальной памяти эффективно работает только в том случае, если выполняется принцип локальности. Если же программа интенсивно использует совокупность данных, не помещающихся полностью в физическую память, будет происходить постоянный "своппинг" — обмен между физической памятью и диском. А так как операции с диском выполняются на несколько порядков медленнее обмена с ЗУ, доступ к памяти в этом случае будет замедлен настолько, что само функционирование прикладной программы оказывается под угрозой.
Посмотрим, как реализован механизм виртуальной памяти в процессорах Intel x86. Из общего принципа виртуальной памяти следует, что возникает необходимость выгружать на диск и загружать с диска группы данных из ЗУ. При этом для каждой такой группы данных должен существовать описатель, в котором будет храниться информация о присутствии или отсутствии данных в физической памяти. На первый взгляд для этой цели можно было бы использовать уже известные нам сегменты. Но их использование не очень удобно по ряду причин: сегмент может иметь достаточно большой размер и выгрузка его целиком на диск будет занимать достаточно большое время; кроме того, все сегменты имеют разный размер и это усложнит логику "своппинга". Гораздо удобнее было бы оперировать "кусочками" адресного пространства небольшого и одинакового размера.
Основой построения механизма виртуальной памяти в МП Intel x86 является механизм страничной адресации. Основная его идея в том, что все адресное пространство разбивается на "страницы" размером 4 Кб. В определенной области ЗУ формируется таблица страниц, каждая строка которой содержит описатель конкретной страницы. Этот описатель включает в себя следующую информацию:
Механизм преобразования логического адреса ячейки ЗУ в физический в данном случае выглядит следующим образом (рис. 1).
Рис. 1.  
Первая часть преобразования выглядит так же, как и в случае защищенного режима. Но после суммирования начального адреса сегмента со смещением получается не физический адрес ячейки памяти, а так называемый "линейный" адрес. Это своего рода "теоретический" адрес, который имеет требуемая ячейка памяти в виртуальном адресном пространстве размером 4 Гб. Дальнейшие преобразования необходимы для того, чтобы понять, в какую реальную ячейку физической памяти отображается этот "теоретический" адрес. Для этого старшая часть линейного адреса используется как индекс в таблице страниц, по нему находится описатель нужной страницы, определяется реальный адрес ее начала в физической памяти, суммируется со смещением ячейки относительно начала страницы (младшие 12 бит линейного адреса) и в результате получается полный физический адрес запрашиваемой ячейки в физической памяти, который в конечном итоге выдается на шину адреса МП.
На этапе обращения к таблице страниц производится проверка наличия запрашиваемой страницы в физической памяти (путем проверки соответствующего признака в описателе страницы). Если страницы в физической памяти нет, процессор вырабатывает исключение отказа страницы. По сути дела, это аппаратное прерывание, обработчик которого (он является частью ОС) должен выполнить следующие действия
  1. По определенному алгоритму выгрузить из физической памяти одну из страниц на диск (например, страницу, к которой дольше всего не было обращений), чтобы освободить место в физической памяти.
  2. Промодифицировать описатель для выгруженной страницы в таблице страниц, пометив ее как не присутствующую в физической памяти.
  3. Найти на диске и загрузить в физическую память (на место выгруженной страницы) запрашиваемую страницу.
  4. Промодифицировать описатель для запрашиваемой страницы в таблице страниц, пометив ее как присутствующую в физической памяти и занеся ее реальный физический адрес в описатель.
После окончания работы обработчика прерывания страничного отказа, процессор повторяет выполнение команды, вызвавшей отказ. Так как в этот момент требуемая страница уже будет присутствовать в физической памяти, вычисление физического адреса пройдет успешно.
Как видно из вышесказанного, механизм виртуальной памяти работает незаметно ("прозрачно") для прикладной программы, у которой создается полная иллюзия работы с физической памятью большого объема.