Часто используемым виртуальным адресам обычно соответствуют элементы в TLB, который обеспечивает чрезвычайно быструю трансляцию виртуальных адресов в физические, а в результате и быстрый доступ к памяти. Если виртуального адреса в TLB нет, он все еще может быть в памяти, но для его поиска понадобится несколько обращений к памяти, что увеличит время доступа. Если виртуальный адрес оказался в страничном файле или если диспетчер памяти изменил его РТЕ, диспетчер памяти должен явно объявить соответствующий элемент TLB недействительным. Если процесс повторно обращается к нему, генерируется ошибка страницы, нужная страница загружается обратно в память и для нее вновь создается элемент TLB.
Диспетчер памяти по возможности обрабатывает аппаратные и программные PTE одинаково. Так, при объявлении недействительного PTE действительным диспетчер памяти вызывает функцию ядра, которая обеспечивает аппаратно-независимую загрузку в TLB нового PTE. B х86-системах эта функция заменяется командой NOP, поскольку процессоры типа x86 самостоятельно загружают данные в TLB.
Physical Address Extension (PAE)
Режим проецирования памяти Physical Address Extension (PAE) впервые появился в х86-процессорах Intel Pentium Pro. При наличии соответствующей поддержки со стороны чипсета в режиме PAE можно адресоваться максимум к 64 Гб физической памяти на текущих х86-процессорах Intel и к 1024 Гб на х64-процессорах (хотя в настоящее время Windows ограничивает этот показатель 128 Гб из-за размера базы данных PFN, которая понадобилась бы для проецирования такого большого объема памяти). При работе процессора в режиме PAE блок управления памятью (memory management unit, MMU) разделяет виртуальные адреса на 4 поля (рис. 7-21).
При этом MMU по-прежнему реализует каталоги и таблицы страниц, но создает над ними третий уровень — таблицу указателей на каталоги страниц. РАЕ-режим позволяет адресовать больше памяти, чем стандартный, — но не из-за дополнительного уровня трансляции, а из-за большего размера PDE и PTE (по 64 бита вместо 32). Внутренне система представляет физический адрес 25 битами, что позволяет поддерживать максимум 225+12 байтов, или 128 Гб, памяти. Для 32-разрядных приложений один из способов использования конфигураций с такими большими объемами памяти был представлен в разделе «Address Windowing Extensions» ранее в этой главе. Ho, даже если приложения не обращаются к таким функциям, диспетчер памяти все равно задействует всю доступную физическую память под данные файлового кэша (см. раздел «База данных PFN» далее в этой главе).
Как мы поясняли в главе 2, существует специальная версия 32-разрядного ядра с поддержкой PAE — Ntkrnlpa.exe. Для загрузки этой версии ядра укажите в Boot.ini параметр /РАЕ. Заметьте, что она устанавливается во всех 32-разрядных системах Windows, даже в системах Windows 2000 Professional или Windows XP с малой памятью. Цель — упростить тестирование драйверов устройств. Поскольку в РАЕ-ядре драйверы устройств и другой системный код используют 64-разрядные адреса, загрузка с параметром /РАЕ позволяет разработчикам тестировать свои драйверы на совместимость с системами, имеющими большие объемы памяти. Кстати, в связи с этим Boot.ini поддерживает еще один параметр — /NOLOWMEM, который запрещает использовать первые 4 Гб памяти (предполагается, что на компьютере установлено минимум 5 Гб физической памяти) и модифицирует адреса драйверов устройств для размещения выше этой границы, что гарантирует выход физических адресов драйверов за пределы 32-разрядных значений.
Трансляция виртуальных адресов на платформе IA64
Виртуальное адресное пространство на платформе IA64 аппаратно делится на восемь регионов. У каждого региона свой набор таблиц страниц. Windows использует только пять регионов, закрепляя таблицы страниц за тремя из них. Все регионы перечислены в таблице 7-12.
При трансляции адресов 64-разряднои Windows на платформе IA64 используется трехуровневая схема таблиц страниц. Каждый процесс получает специальную структуру, содержащую 1024 указателя на каталоги страниц. Каждый каталог страниц содержит 1024 указателя на таблицы страниц, а те в свою очередь указывают на страницы физической памяти. Формат аппаратных PTE на платформе IA64 показан на рис. 7-22.
Трансляция виртуальных адресов на платформе x64
64-разрядная Windows на платформе х64 применяет четырехуровневую cxe-мутаблиц страниц. У каждого процесса имеется расширенный каталог страниц верхнего уровня (называемый картой страниц уровня 4), содержащий 512 указателей на структуру третьего уровня — родительский каталог страниц. Каждый родительский каталог страниц хранит 512 указателей на каталоги страниц второго уровня, а те содержат по 512 указателей на индивидуальные таблицы страниц. Наконец, таблицы страниц (в каждой из которых 512 PTE) указывают на страницы в памяти. B текущих реализациях архитектуры x64 размер виртуальных адресов ограничен 48 битами. Элементы 48-битного виртуального адреса представлены на рис. 7-23. Взаимосвязь между этими элементами показана на рис. 7-24, а формат аппаратного PTE на платформе x64 приведен на рис. 7-25.
Обработка ошибок страниц
Мы уже разобрались, как происходит трансляция адресов при действительных РТЕ. Если битовый флаг Valid в PTE сброшен, это значит, что нужная страница по какой-либо причине сейчас недоступна процессу. Здесь мы расскажем о типах недействительных PTE и о том, как разрешаются ссылки на такие РТЕ.
ПРИМЕЧАНИЕ B этой книге детально рассматриваются только PTE на 32-разрядной платформе x86. PTE для 64-разрядных систем содержат аналогичную информацию, но их подробную структуру мы не описываем.
При ссылке на недействительную страницу возникает ошибка страницы (page fault), и обработчик ловушки ядра (см. главу 3) перенаправляет ее обработчику MmAccessFault диспетчера памяти. Последняя функция, выполняемая в контексте вызвавшего ошибку потока, предпринимает попытку ее разрешения (если это возможно) или генерирует соответствующее исключение. Причины таких ошибок перечислены в таблице 7-13.
B следующем разделе описываются четыре базовых типа недействительных РТЕ. Затем мы рассмотрим особый случай недействительных PTE — прототипные РТЕ, используемые для поддержки разделяемых страниц.
Недействительные PTE
Ниже приведен список типов недействительных PTE с описанием их структуры. Некоторые их флаги идентичны флагам аппаратных PTE (см. таблицу 7-11).
• PTE для страницы в страничном файле (page file PTE) Нужная страница находится в страничном файле. Инициируется операция загрузки страницы.
• PTE для страницы, обнуляемой по требованию (demand zero PTE)
Нужная страница должна быть заполнена нулями. Сначала просматривается список обнуленных страниц (zero page list). Если он пуст, просматривается список свободных страниц (free list). Если в нем есть свободная страница, она заполняется нулями. Если этот список тоже пуст, используется список простаивающих страниц (stanby list). Формат этого PTE идентичен формату PTE для страницы в страничном файле, но номер страничного файла и смещение в нем равны 0.