Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Разработка операционных систем - для начинающих и не только!


Информационный Канал Subscribe.Ru

Разработка операционных систем

Выпуск 19 от 2003-06-30

Сегодня в номере:

Реализация виртуальной памяти на IA-32 (x86)

IA-32 - уникальная архитектура, в том смысле, что она поддерживает одновременно как сегментацию, так и страничную адресацию. (как уже говорилось, в большинстве современных микропроцессоров сегментации нет).

Сегментация

Для реализации виртуальной памяти с помощью сегментов в многозадачной системе необходимо, чтобы каждый процесс мог иметь свой собственный набор сегментов. На IA-32 это реализуется несколькими способами:

1) Способ первый, притянутый за уши: в GDT описываются все сегменты всех процессов и при переключении процесса в сегментные регистры загружаются соответствующие дескрипторы.
2) Способ второй, ненамного лучше первого: при переключении процессов заменяется GDT (теперь селекторы сегментов у разных процессов могут быть одинаковыми, но соответствующие им дескрипторы будут различны)
3) Способ третий, оптимальный: кроме глобальной таблицы дескрипторов GDT существует и локальная таблица дескрипторов LDT. Соответственно, при переключении процессов эту таблицу можно заменить и опять же новый процесс окажется со своими сегментами.

По поводу реализации вышеозначенных методов отсылаю читателя к руководству от Intel (у кого его еще нет - бегом на developer.intel.com заказывать, пока бесплатно). Но, повторюсь, что сегментация устарела и вряд ли может иметь смысл реализация сегментации в операционной системе общего назначения (а вот в какой-нибудь узкоспециализированной RTOS - наверняка)

Страничная адресация

А вот со страничной адресацией мы разберемся поподробнее, поскольку она позволяет проделывать такое, что приверженцам сегментации и не снилось :).

Для начала отключим сегментацию, чтобы она нам не мешала. Фактически. сегментация в IA-32 действует всегда и отключить ее нельзя, но можно сделать ее максимально прозрачной. Для этого достаточно загрузить все сегментные регистры дескрипторами сегментов с базой 0 и лимитом 4Гб.Все! Теперь в нашем распоряжении в свободном доступе имеется все адресное пространство. (именно в такое состояние переводит процессор загрузчик, который мы написали ранее)

Страничная адресация, в отличие от сегментации, по умолчанию отключена и включается установкой бита 31 регистра CR0. Но прежде чем мы ее включим, нам необходимо создать рабочий каталог страниц и поместить его в регистр CR3 (также называемый PDBR - page directory base register).

На этом месте необходимо отметить, что более новые модели IA-32 поддерживают различные размеры страниц и для нестандартных страниц структура каталога может отличаться от нижеприведенной. Мы рассмотрим страничную адресацию с использованием классических 4-килобайтных страниц

Что представляет из себя каталог страниц? Он состоит из 1024 указателей на таблицы страниц (они именуются записями каталога страниц или PDE - page directory entry), которые имеют тип dword. (если указатель на каталог имеет вид int *pagedir, то pagedir[n] будет n-ым PDE)

Таблица страниц представляет из себя 1024 указателя на физические страницы (эти указатели именуются записями таблицы страниц или PTE - page table entry), которые также имеют тип dword

Каждая таблица страниц (и каждая страница) обязана быть выровнена по 4-кб адресу. А это означает, что младшие 12 бит PDE и PTE не используются при указании адреса

Эти 12 бит описывают параметры страницы или таблицы страниц и имеют следующий формат:

  • бит 0 - флаг "страница физически существует"
  • бит 1 - флаг "запись в страницу разрешена"
  • бит 2 - флаг "пользователь (ring3) имеет доступ к странице"
  • бит 3 - флаг "кэширование write back (0) / write through (1)"
  • бит 4 - флаг "кэширование запрещено"
  • бит 5 - флаг "к странице было обращение" - устанавливается процессором
  • бит 6 - флаг "была произведена запись в страницу" - устанавливается процессором
  • бит 7 - флаг "большая страница" (нас пока не интересует)
  • бит 8 - флаг "глобальная страница" (о них попозже)
  • биты 9-11 - доступны для использования операционной системой

Разберемся, как же процессор получает физический адрес виртуальной страницы. Допустим было произведено обращение к адресу 0x80050075 (двоичное 1000 0000 0000 0101 0000 0000 0111 0101). Если страничная адресация включена, то:

  • Из регистра CR3 достается адрес каталога страниц (к примеру это 0x00400000)
  • Биты 31-22 адреса определяют номер таблицы в каталоге. В нашем случае это 10 0000 0000 или десятичное 512.
  • Из каталога вытаскивается PDE с полученным номером (к примеру это 0x00500007)
  • Процессор смотрит бит 0 PDE. В нашем случае он равен 1 - значит все в порядке, данная таблица присутствует в памяти
  • Биты 31-12 PDE определяют физический адрес таблицы в памяти (в нашем случае искомый адрес: 0x00500000)
  • Процессор возвращается к запрошенному адресу и смотрит на биты 21-12, которые определяют номер страницы в таблице (в нашем случае это 00 0101 0000 или десятичное 40)
  • Из таблицы страниц вытаскивается PTE имеющее нужный номер (к примеру PTE равно 0x00971007)
  • Процессор смотрит бит 0 PTE. В нашем случае это 1 - значит данная страница присутствует в памяти
  • Биты 31-12 PTE определяют физический адрес страницы в памяти (в нашем случае: 0x00971000)
  • Процессор возвращается к запрошенному адресу и смотрит на биты 11-0, которые определяют смещение в странице. (в нашем случае это: 0000 0111 0101 или шестнадцатеричное 0x75)
  • Значения полученные на предыдущих двух шагах OR'ятся друг с другом и в результате получается искомый физический адрес (в нашем случае это - 0x00971075)

Разумеется, кроме проверки на существование страницы (бит 0 PDE или PTE) осуществляются и другие, но для ясности их мы опустили. Чем же эта проверка так отличается от других? Дело в том, что если вдруг процессор замечает, что таблица/страница не существует, то он немедленно сигнализирует об этом с помощью Page Fault и не смотрит на остальные биты (в которых, к примеру, операционная система может хранить информацию о том, где же на самом деле находится эта страница). То есть, если бит 0 равен 0, то ВСЕ ОСТАЛЬНЫЕ биты PTE или PDE доступны для использования операционной системе

Алгоритм нахождения адреса, приведенный выше, слишком медлителен, и использование его при каждом обращении к памяти привело бы к существенному понижению скорости работы. Поэтому адреса страниц кэшируются и если обращение происходило недавно, то процессор достает адрес страницы из кэша TLB (translation lookaside buffer)

Установленный бит 8 "глобальная страница" определяет, что адрес страницы НЕ выгружается из TLB при перезагрузке CR3. Поясним на примере. В ОС Tyros младшие два гигабайта адресного пространства (0x00000000 - 0x7FFFFFFF) являются системными (флаг "пользователь" снят) и на равных принадлежат всем процессам. Разумеется, что при переключении процессов эта часть адресного пространства не изменяется. Соответственно установленный бит 8 приходится очень кстати - не теряется время на выгрузку этой части из TLB и загрузку ее заново

В следующем выпуске мы продолжим разговор о реализации виртуальной памяти

Outro

На сегодня все, уважаемые подписчики.
Как всегда, мой почтовый ящик открыт для вас: lonesome@lowlevel.ru
Также вы можете задавать интересующие вас вопросы в форуме lowlevel.ru
Предыдущие выпуски рассылки вы можете найти по этому адресу:
http://subscribe.ru/archive/comp.soft.prog.osdev
А все, исходники, опубликованые в рассылке, располагаются здесь:
http://www.lowlevel.ru/osdev/sources.htm
Всего наилучшего!
Lonesome



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное