Каталоги страниц и таблицы страниц
В архитектуре х86 преобразование линейного адреса (или логического адреса — в Linux они совпадают) в физический адрес представляет собой двухэтапный процесс, который схематически показан на рис. 8.2. Линейный адрес, предоставляемый процессом, делится на три части: индекс каталога страниц, индекс таблицы страниц и смещение. Каталог страниц — это массив указателей на таблицы страниц, а таблица страниц — это массив указателей на страницы, поэтому преобразование адреса предусматривает прохождение по цепочке указателей. Каталог страниц позволяет найти таблицу страниц, которая указывает на конкретную страницу, а смещение позволяет перейти к адресу на странице.
8.2. Страничный обмен в x86
Опишем этот процесс более подробно и точно: вход каталога страницы в данном индексе каталога страниц содержит адрес таблицы страниц, которая хранится в физической памяти; вход таблицы страниц в данном индексе таблицы страниц содержит базовый адрес в физической памяти соответствующей физической страницы, и с этим физическим адресом складывается смещение линейного адреса для вычисления окончательного искомого адреса на физической странице.
В других процессорах предусмотрен трехуровневый подход, как показано на рис. 8.3. Это особенно удобно в 64-разрядных архитектурах типа Alpha, где более обширное 64-разрядное адресное пространство при использовании преобразования адресов по принципу х86 потребовало бы применения огромных каталогов страниц, таблиц страниц или смещений, или всех трех одновременно. В связи с этим разработчики Alpha ввели еще один уровень в схему линейных адресов, который в системе Linux называется «промежуточным каталогом страниц»; он находится между каталогом страниц и таблицей страниц.
8.3. Представление ядра о страничном обмене
Итак, в действительности страничная адресация — это метод, аналогичный описанному выше, но еще с одним уровнем. В трехуровневом подходе снова применяется каталог страниц, каждый из входов которого содержит адрес промежуточного каталога страниц, каждый из входов которого содержит адрес таблицы страниц, каждый из входов которой, как и прежде, содержит адрес страницы в физической памяти, с которым нужно сложить смещение для получения окончательного адреса.
Только для того, чтобы запутать вопрос еще больше, заметим, что схема трехсоставного адреса ассоциируется с двухуровневым преобразованием адреса, а схема четырехсоставного адреса ассоциируется с трехуровневым преобразованием адреса. Это связано с тем, что «уровни», о которых мы обычно говорим, не включают первого этапа индексации, с переходом в каталог страниц (поскольку, по мнению автора, это — не преобразование).
Нет ничего неожиданного в том, что разработчики ядра решили иметь дело только с одной из этих схем. В основной части кода ядра все модули MMU рассматриваются одинаково, то есть так, как если бы в них всегда применялась трехуровневая процедура (то есть четырехсоставные адреса). В архитектуре х86 макрокоманды адресации страниц успешно заменяют трехуровневое преобразование двухуровневым, устанавливая размер промежуточного каталога страниц равным единице. За пределами действия макрокоманд промежуточный каталог страниц считается почти равнозначным каталогу страниц, поэтому в основном коде ядра остается возможность обрабатывать адреса так, как если бы они состояли из четырех частей.
В архитектуре х86 десять битов каждого 32-разрядного адреса отведено для индекса каталога страниц, еще 10 битов — для индекса таблицы страниц, а оставшиеся 12 битов отведено для смещения. Вот почему размер страницы равен 4 Кб — 12 битов соответствует 4096 смещениям.
Функции и макрокоманды для создания и управления входами на каждом уровне определены в файлах include/asm-i386/page.h (строка ) и include/asm-1386/pgtable.h (строка ). Просматривая эти функции и макрокоманды, помните, что PGD обычно означает «вход каталога страниц»(а не просто «каталог страниц»), PMD обычно означает «вход промежуточного каталога страниц» (а не просто «промежуточный каталог страниц»), а РТЕ обычно означает «вход таблицы страниц». Кроме того, как подчеркивает наречие «обычно» в предыдущей фразе, существуют исключения, например, функция pte_alloc, которая рассматривается далее в этой главе, распределяет таблицу страниц, а не вход таблицы страниц (как можно было предположить). К сожалению, обсуждение всех этих программных процедур могло бы занять в этой главе больший объем, чем для нее отведено. Однако некоторые из них далее будут рассмотрены.
Входы таблицы страниц регистрируют не только базовый адрес страницы, но и признаки ее защиты — набор флажков, обозначающих страницу как предназначенную для чтения, записи и/или выполнения (вполне очевидно, что они напоминают по смыслу биты защиты файла). Вход таблицы страниц включает еще несколько других флажков, свойственных для конкретной страницы, как будет описано ниже при более подробном рассмотрении средств защиты страниц.
Содержание раздела