Ну вот, наконец-то мы добрели и до страничной адресации (не прошло и месяца :). Стоит отметить, что подписчики, у которых не возникло проблем с сегментной адресацией также легко и просто освоят страничную.
Прежде всего, нужно понять очень важную вещь: при использовании страничной адресации структуры из сегментной адресации (как то – таблицы дескрипторов, селекторы, регистры таблиц дескрипторов) НИКУДА НЕ ДЕВАЮТСЯ! Все остается на своих местах! Так в чем же тогда заключается страничная адресация? Где же она себя проявляет?
ВАЖНЫЙ МОМЕНТ: ЕДИНСТВЕННОЕ МЕСТО, ГДЕ СТРАНИЧНАЯ АДРЕСАЦИЯ ДЕЙСТВИТЕЛЬНО ВКЛИНИВАЕТСЯ В ПРОЦЕСС РАБОТЫ ПРОЦЕССОРА – ПРИ ПЕРЕВОДЕ ЛИНЕЙНОГО АДРЕСА В ФИЗИЧЕСКИЙ! Вот в этом вся соль! ЭТИМ НУЖНО ПРОНИКНУТЬСЯ!
Придется немного прокрутить пленку назад. Вспомни три понятия: логический, линейный и физический адрес. Логический адрес – это некий абстрактный, на деле ничего не значащий адрес, грубо говоря, CS:EIP – это и есть логический адрес, в самом деле, что он может нам сообщить? Ничего. Только то, что если мы вытащим из CS поле индекс, а затем по этому полю найдем в таблице дескрипторов соотв. дескриптор, а затем к базе из этого дескриптора прибавим EIP – то вот только тогда получим ЛИНЕЙНЫЙ адрес. При использовании сегментной адресации физический адрес совпадает с линейным (физический – это адрес который проц выставляет уже на адресную шину). Т.е. при сегментной адресации проц просто берет линейный адрес и без выкрутасов выставляет на адресную шину.
При использовании страничной адресации именно на этапе перевода линейного адреса в физический в действие вступают новые силы, о коих и будет поведано ниже...
При использовании страничной адресации линейный адрес не совпадает с физическим, как в случае с сегментной адресацией. Т.е. мы имеем дело с виртуальной памятью. Процессор делит линейное адресное пространство на страницы фиксированного размера (длиной 4Кб, 2Мб или 4Мб), которые, в свою очередь, уже отображаются в физической памяти (или на диске). Когда программа (или задача) обращается к памяти через логический адрес, процессор переводит его в линейный и затем, используя механизму страничной адресации, переводит его в соответсвтующий физический адрес. Если страницы в данный момент нет в физической памяти, то возникает исключение #PF. Это по сути кульминационный момент: обработчик этого исключения (#PF) должен выполнить соответствующие манипуляции по устранению данной проблемы, т.е. подгрузить страницу с харда (или наоборот – скинуть ненужную страницу на диск).
Вообщем, все знают что такое своп-файл в винде? Вот по сути это и есть те самые странички памяти на харде, которые после возникновения #PF должны быть загружены в оперативку (или наоборот). По сути - #PF это не есть нечто ужасное и недопустимое (как #GP). НАОБОРОТ! #PF «нам строить и жить помогает!!!» Без него вообще ничего бы и не получилось по сути то дела!
Как только страница была благополучно водворена на место, то выполнение прерванной проги продолжается с той самой инструкции, которая вызвала #PF. А кстати, какая инструкция может вызвать #PF? Да в принципе любая, которая так или иначе обращается к памяти...
Страничная организация отличается от сегментной еще и тем, что все страницы имеют фиксированный размер (в сегментной размер сегментов абсолютно произволен). Также при сегментной адресации все сегменты обязательно должны присутствовать непосредственно в оперативе, а при страничной возможна ситуация, когда кусок сегмента находится в памяти, а другой кусок фактически того же сегмента – на харде (т.е. другими словами – часть страниц сегмента находится в оперативе, а часть – валяется в то же время на харде).
Проц всегда, где это возможно, облегчает себе жизнь. Вспомни про «теневую» часть сегментного регистра. Также и в случае со страничной адресацией – страницы, к которым проц чаще всего обращается кэшируются в процессоре, в области, которая называется буфер с ассоциативной выборкой (TLB - Table lookaside buffer). Т.е. не все такие страницы целиком, а только записи, которые необходимы для доступа к ним (см. ниже).
Несколько слов по поводу TLB. Начиная с P6 процев сущестувуют кэши специально для записей, описывающих код и данные, также разные кэши для 4Кб и для 4Мб страниц. Инструкция CPUID позволяет определить размер этих самых TLB в твоем проце. Чем они больше – тем быстрее соответственно будет работать проц. В отличии от теневой части сегментного регистра, куда мы не могли лезть руками и вообще не имели никакого доступа к ней, в TLB мы можем кое что изменять (естественно только в том случае, если мы на самом крутом уровне привилегий, на нулевом). Для этого существует команда INVLPG и др. приемы, на которых не стоит заострять внимания (если кому интересно в подробностях – пишите).
Итак, страничная организация непосредственно в проце управляется тремя флажками:
1. Флаг PG (paging): бит 31 в регистре CR0. Появился в 386 проце.
2. Флаг PSE (page size extensions): бит 4 в регистре CR4. Появлися в пнях.
3. PAE (physical address extension) flag: бит 5 в регистре CR4. Появился в пентиум pro процах.
Теперь подробнее. Флаг PG разрешает страничную адресацию. Сразу после установки его в единицу страничная адресация включена.
Флаг PSE, если его установить, позволяет использовать страницы больших размеров (4Мб и 2Мб). Если сброшен – страницы имеют размер 4Кб.
Флаг PAE позволяет расширить физический адрес до 36 бит (стандартно он 32-х битный). Данный флаг можно использовать ТОЛЬКО в режиме страничной адресации. Узнать, поддерживает ли твой проц данное расширение можно по 17 биту в EDX после CPUID).
Кстати, использовать 36-разрядную адресацию можно как с помощью PAE-флага, так и с помощью PSE-флага, это два разных метода, мы их рассмотрим дальше.
|