В состав набора регистров Pentium входят следующие группы:
1. Регистры общего назначения. Эта группа включает восемь 32-битовых регистров. Их можно использовать в любых командах программы, в том числе и для хранения данных, необходимых для вычисления исполнительного адреса в сложных режимах адресации. Кроме того, некоторые из регистров этой группы имеют определенную специализацию. Например, команды работы с символьными строками используют содержимое регистров ECI, ESI и EDI в качестве операндов, хотя явно в коде команды это и не указывается. Такой подход позволяет несколько сократить размер кода команды.
2. Регистры сегментов. Шесть 16- битовых регистров предназначенных для хранения информации о сегментах.Регистр сегмента программного кода, CS, хранит индекс сегмента, содержащего команды программы, выполняемой в текущий момент времени. Регистр стека, SS, указывает сегмент, в котором размещен программно доступный стек. Остальные регистры сегментов (DS, ES,FS,GS) позволяют обращаться в программе к четырем разным сегментам данных.
3. Флаги. Регистр EFLAGS содержит коды условий и различные биты состояния. Содержит информацию о текущем состоянии процессора и помогает управлять его функционированием. Шесть битов регистра содержат коды условий, сформированные по результату выполнения последней арифметической или логической команды с целыми числами (перенос, четность, дополнительный перенос, нуль, знак, переполнение). Кроме того, в этом регистре имеются биты, которые можно рассматривать как управляющие.
· Флаг следящего прерывания. (TF -trap flag). Если этот флаг установлен, процессор выполняет программу в режиме следящего прерывания, т.е. после завершения очередной команды формируется запрос прерывания. Этот режим используется при отладке программ.
|
· Флаг разрешения внешнего прерывания. (IF - interrupt enable flag). Если этот флаг установлен, процессор реагирует на поступающие извне запросы прерываний.
· Флаг направления (DF - direction flag). Флаг определяет, происходит ли при обработке строк инкрементирование или декрементирование содержимого 16- битовых полурегистров SI и DI (при обработке 16- битовых данных) или содержимого 32 - битовых регистров ESI и EDI при обработке 32 - битовых данных.
· Флаг привилегированного ввода-вывода (IOPL- I/O privilege flag). Если этот флаг установлен, процессор формирует сообщение об исключительной ситуации при всех обращениях к устройствам ввода - вывода во время выполнения операций в защищенном режиме.
· Флаг возобновления (RF- resume flag). Этот флаг позволяет программисту заблокировать формирование сообщений об исключительных ситуациях при отладке, и, таким образом, команда может быть вновь запущена на выполнение после обработки исключительной ситуации отладки, что не приведет к немедленному формированию еще одного сообщения.
· Проверка выравнивания (AC- alignment check). При установленном флаге формируется прерывание, если при адресации слова или двойного слова не соблюдается кратность адреса длине слова или двойного слова.
· Флаг идентификации (ID - identification flag). Этот бит можно изменять в процессорах, которые поддерживают выполнение команды CPUID. Команда дает возможность получить информацию об изготовителе, семействе, к которому принадлежит процессор, и его модели.
|
Кроме того, в регистре имеется еще 4 бит, которые имеют отношение к режиму функционирования процессора. Флаг вложенных задач (NT - nested task)- индикатор, показывающий, вложена ли текущая задача в другую задачу в защищенном режиме работы процессора. Бит виртуального режима (VM- virtual mode) позволяет программисту разрешить или запретить виртуальный режим процессора 8086, т.е. режим, в котором процессор Pentium эмулирует процессор 8086. Флаг виртуального прерывания (VIF virtual interrupt flag) и флаг отложенного виртуального прерывания (VIP - virtual interrupt pending flag) используют в многозадачной операционной системе.
4. Указатель текущей команды. Этот регистр содержит адрес текущий команды. Блок обработки чисел в формате с плавающей точкой имеет собственные специализированные регистры.
5. Числовые регистры. Каждый регистр этой группы способен хранить 80- битовое число в формате с плавающей точкой. Регистры работают как единый стек, и по отношению к ним можно использовать операции заталкивания в стек и выталкивания из стека, которые имеются в наборе команд процессора.
6. Регистры управления. Четыре 32-битовых регистра управления (регистр CR1 не используется), с помощью которых контролируется различные аспекты функционирования процессора. Регистр CR0 содержит флаги управления, которые контролируют режим работы процессора и являются индикаторами не столько состояния выполняемой программы, сколько процессора в целом.
· Разрешение защищенного режима (PE - protection enable). Разрешение/запрет защищенного режима функционирования процессора.
· Мониторинг сопроцессора (MP - monitor coprocessor). Используется при выполнении на Pentium программ, разработанных для прежних моделей процессоров Intel 8086; бит имеет отношение к работе арифметического сопроцессора.
|
· Эмуляция (EM- emulation). Устанавливается в тех процессорах, которые не имеют встроенного блока обработки чисел в формате с плавающей точкой. Если этот бит установлен, то при попытке выполнить команду обработки чисел в формате с плавающей точкой формируется прерывание.
· Переключаемые задачи (TS - task switched). Индикатор выполнения переключаемых задач.
· Расширенный тип (ET- extension type). Не используется в процессоре Pentium. В прежних моделях процессоров Intel 8086 использовался в качестве индикатора поддержки функционирования арифметического сопроцессора Intel 8087.
· Числовая ошибка (NE-numeric error). Разрешает функционирование стандартного механизма формирования сообщений об ошибках выполнения арифметических команд на линиях внешней магистрали.
· Защита записи (WP write protect).Если этот бит не установлен, супервизорный процесс может записывать информацию в страницы памяти прикладных программ, имеющий статус "только для чтения". В некоторых операционных системах такая возможность используется для поддержки операций формирования программных процессоров.
· Маска выравнивания (AM - alignment mask). Разрешает/запрещает проверку выравнивания адресов по границе слова или двойного слова.
· Не выполнять сквозную запись (NM- not write through). Этот бит контролирует режим записи информации из кэша в оперативную память. Когда бит установлен, разрешается режим сквозной записи.
· Блокировка кэша (CD- cache disable).Разрешает/запрещает работу внутреннего механизма заполнения кэша.
· Страничный обмен (PG- paging). Разрешает/запрещает работу механизма страничного обмена.
Регистры Cr2 и CR3 используются в режиме страничного обмена (т.е. при установленном бите PG). В регистре CR2хранится 32- разрядный линейный адрес последней страницы, к которой произошло обращение перед прерыванием отсутствия страницы. Старшие 20 разрядов CR3 содержат значения 20 старших разрядов базового адреса каталога страниц, а оставшиеся разряды - коды 0. Два бита регистра CR2и CR3 используется для управления сигналами на выводах внешнего блока кэш-памяти. Бит блокировки кэша страничного уровня -PCD- разрешает или запрещает работу с внешним блоком кэша, а бит сквозной записи кэша страничного уровня - PWT- управляет сквозной во внешний кэш.
В регистре CR4 имеется девять управляющих битов:
· Расширенный виртуальный режим 8086 - разрешает поддержку флага виртуального прерывания в виртуальном режиме 8086
· Виртуальные прерывания в защищенном режиме - разрешает поддержку флага виртуального прерывания в защищенном режиме.
· Запрет отметок времени - запрещает чтение из счетчика отметок времени по команде RDSD, которая используется в режиме отладки.
· Расширение отладочного режима - разрешает установку точек останова на операциях ввода-вывода. Если такая точка останова существует, процессор вырабатывает сигнал запроса прерывания при операциях чтения или записи на устройство ввода-вывода.
· Расширение размера страницы - разрешает использование страниц размером 4 Мбайта в процессоре Pentium и страниц размером 2 Мбайта в процессорах Pentium Pro и Pentium2.
· Расширение физического адреса -разрешает обработку сигналов на линиях адреса А35-А32, если задан новый режим адресации битом PSE.
· Расширение контроля магистрали - разрешает формирование сигнала запроса прерывания при обнаружении ошибки четности данных во время цикла чтения магистрали, или когда цикл магистрали не завершился нормально.
· Разрешение глобальных страниц - разрешает использование глобальных страниц. Если этот бит установлен и выполняется переключение задач, все элементы буфера быстрой переадресации -TLB- сбрасывается за исключением тех, которые помечены как глобальные.
· Разрешение работы счетчиков сбора статистики- разрешает выполнение команды RDPMC (чтение счетчика сбора статистики) на любом привилегированном уровне. В процессоре имеются два счетчика сбора статистики, с помощью которых можно измерить длительность событий определенного типа и количество появлений событий определенного типа.
7. Регистр статуса. Отдельные биты этого 16- битового регистра несут информацию о текущем состоянии блока обработки чисел в формате с плавающей точкой. В частности, в нем хранится 3- битовый указатель стека, флаги, характеризующие результат последней арифметической операции, флаги исключительных ситуаций.
8. Слово тэга. Этот 16- битовый регистр содержит 2- битовые коды тэгов для каждого из числовых регистров, которые определяют характер содержимого регистра, связанного с тэгом. Четыре возможных кодовых комбинаций значения тэга имеют следующий смысл: значение достоверно, значение равно нулю, в регистре находится специальный код (NaN, бесконечность, ненормализованное число), регистр пуст (его содержимое случайно и не несет никакой информации). Коды тэгов позволяют программно анализировать содержимое числовых регистров без выполнения сложных арифметических операций с данными в этих регистрах. Например, при выполнении операции сохранения текущего состояния процессора можно не записывать в память содержимое регистра, если соответствующий тэг указывает, что регистр пуст.
GDT (англ. Global Descriptor Table, глобальная таблица дескрипторов) — служебная структура данных в архитектуре x86, определяющая глобальные (общие для всех задач) сегменты. Её расположение в физической памяти и размер определяются системным регистром GDTR.
Дескрипторы LDT и сегментов задач (TSS) могут находиться только здесь.
Особенностью GDT является то, что у неё запрещён доступ к первому (то есть нулевому) дескриптору. Обращение к нему вызывает исключение #GP, что предотвращает обращение к памяти с использованием незагруженного сегментного регистра.
GDTR
GDTR (англ. G lobal D escriptor T able R egister — регистр глобальной дескрипторной таблицы) — специальный 48-битный регистр, который описывает местоположение и размер таблицы, содержащей дескрипторы. Он появился вместе с механизмом защиты в 80286 моделях процессоров как сегментный механизм защиты.
Регистр содержит два поля: первое поле — первые 32 бита, описывают линейный адрес, по которому должна быть расположена дескрипторная таблица, а последние 16 бит — лимит, определяющий размер таблицы в байтах. Каждый дескриптор занимает в памяти по 8 байт, потому лимит всегда должен вычисляться так: limit = 8*n — 1, где n — количество дескрипторов.
При инициализации операционной системы глобальная дескрипторная таблица обычно создаётся на полное количество дескрипторов (limit = 65535), или 8192 дескрипторов. Затем виртуальный адрес начала таблицы загружается в регистр GDTR специальной ассемблерной инструкцией LGDT (англ. L oad GDT):
mov ax, GDT_Limitpush axmov eax, GDT_Basepush eaxmov bp, splgdt qword [ss:bp]; стек растёт ''вниз''!После включения механизма защиты начинает действовать селекторная система адресации, вместо сегментной, и использоваться GDT.
Локальная дескрипторная таблица
В отличие от GDT, LDT может быть много (соответственно количеству задач (потоков), но не обязательно). Каждая задача может иметь свою. На расположение таблицы текущей задачи указывает регистр LDTR.
Размер и расположение LDT в линейной памяти определяются дескриптором LDT из GDT (но это не означает, что размер LDT может быть больше 65536 байт).
Первый дескриптор LDT (№ 0) использовать можно
Таблица векторов прерываний (англ. Interrupt Descriptor Table, IDT) используется в архитектуре x86 и служит для определения корректного ответа на прерывания и исключения.
В микропроцессорах Intel 8086/80186 таблица векторов прерываний расположена в первом килобайте памяти начиная с адреса 0000:0000 и содержит 256 векторов прерываний в формате сегмент:смещение. Начиная с процессора 80286, адрес в физической памяти и размер таблицы прерываний определяется 48-битным регистром IDTR.
В IDT используются следующие типы прерываний: аппаратные прерывания, программные прерывания и прерывания, зарезервированные процессором, называемые исключениями (первые 32) на случай возникновения некоторых событий (деление на ноль, ошибка трассировки, переполнение).
В реальном режиме элементом IDT является 32-битный FAR-адрес обработчика прерывания.
В защищённом режиме элементом IDT является шлюз прерывания длиной 8 байт, содержащий сегментный (логический) адрес обработчика прерывания, права доступа и др.
В длинном режиме размер дескриптора прерывания увеличен до 16 байт.
В режиме V86 при использовании расширения VME таблица векторов располагается по виртуальному адресу 0000:0000. Без использования этого расширения (и в том случае, если переадресация прерываний запрещена) при возникновении прерывания процессор покидает режим V86 и выполняет обычный обработчик защищённого режима.
При адресации памяти в защищённом режиме команды ссылаются на сегменты, указывая не их адреса (как в режиме реальных адресов), а описания сегментов (их дескрипторы). Указатель на описание сегмента называется селектор. Другими словами, селектор - это номер дескриптора из таблицы дескрипторов.
Адресация производится через пару регистров сегмент:смещение, причём, в качестве сегментного регистра используются обычные CS, SS, DS, ES, FS и GS (последние два появились в 386-м процессоре), но в них указывается не адрес сегмента, а селектор дескриптора.
Селекторы нужны, по крайней мере, по трём причинам:
1. | Описание сегмента занимает 8 байт и использовать 8-байтные сегментные регистры было бы крайне неэффективно. |
2. | Селекторы имеют размер в 16 бит, благодаря чему их можно использовать в сегментных регистрах и обращаться к памяти можно по-прежнему через пару регистров. |
3. | Параметры всех сегментов хранятся в отдельной области памяти, доступ к которой имеет только операционная система. Программа, используя селектор, сможет получить о сегменте совсем немного информации и не сможет изменить параметры сегмента, благодаря чему очень удачно реализуется механизм защиты. |
Адрес памяти можно указывать не только через пару регистров, но и в переменных, через пару значений селектор:смещение.
Можно было бы определить селектор просто, как номер сегмента, но в защищённом режиме кроме сегментов, дескриптор может определять целый ряд других системных объектов (например, задач), поэтому лучше не упрощайте понятия селектора и дескриптора, а постарайтесь привыкнуть к этой терминологии.
Селектор имеет следующий формат:
Рисунок 5-1. Формат селектора.
- Двухбитовое поле RPL (Requested Privilege Level) содержит номер уровня привилегий, которое имеет текущая программа. Значение этого поля процессор использует для защиты по привилегиям. К одному и тому же дескриптору можно обращаться, используя селекторы с разными значениями RPL, но процессор позволит доступ только при определённых условиях (подробнее об этом см. в главе "Защита по привилегиям").
- Бит TI (Table Indicator) определяет таблицу, из которой выбирается нужный дескриптор. Если бит TI = 0, то обращение производится к глобальной дескрипторной таблице GDT (она одна на всю систему), если TI = 1 - то к текущей локальной дескрипторной таблице LDT (таких может быть много).
Подробнее дескрипторные таблицы обсуждаются в соответствующих главах. - Index - это собственной номер дескриптора, от 0 до 8191. Т.к. поле индекса состоит из 13 бит, то максимальное число дескрипторов, одновременно существующих в системе равно 2 13, т.е. 8192. Как видите, это довольно-таки много и вполне удовлетворяет любым системным запросам. На самом деле, число дескрипторов можно значительно увеличить за счёт использования множества дополнительных локальных дескрипторных таблиц.
Использование селекторов достаточно простое. Для тех дескрипторов, которые будут определены заранее, например, сегментов кода, стека и данных, селекторы подготавливаются как константы и затем используются для загрузки в сегментные регистры. Для дескрипторов, которые программа будет динамически создавать, селекторы придётся определять в переменных и загружать в сегментные регистры из памяти либо конструировать "на ходу", или даже как константы - всё зависит от конкретных условий. Способы использования селекторов и дескрипторов вы можете найти в примерах, которые будут следовать в дальнейших главах.
Обращение к дескрипторной таблице процессор производит только в момент загрузки в сегментный регистр нового селектора. После этого содержимое дескриптора копируется в так называемый "теневой регистр", к которому имеет доступ только сам процессор и из которого оно в дальнейшем используется. Любое последующее обращение к сегменту будет происходить с помощью теневого регистра, без обращения к дескрипторной таблице и не потребует лишних тактов на циклы чтения памяти. Правда, эти такты тратятся каждый раз, когда вы загружаете новый селектор, но это не высокая плата за защиту дескрипторов от недозволенного доступа.
При загрузке недопустимого значения селектора процессор будет генерировать исключение, даже если вы не обращались через него к памяти.
В защищенном режиме работы микропроцессоров x86 обеспечивается лучшая защита операционной системы от несанкционированного доступа программ пользователя. Это происходит путем усложнения формирования линейного адреса в микропроцессорах i80386 и выше. Например, сегмент не может быть использован никакой программой, если он не "представлен" ей соответствующим образом. Программа уже не может обращаться по любому адресу, который она может сформировать. При "представлении" сегмента программе она должна запросить не только базовый адрес сегмента, но и уровень привилегий, локализацию сегмента, его длину и разрешающую способность, права доступа к сегменту (чтение, запись и выполнение) и некоторые другие параметры.
При всем этом у системного программиста имеется больше возможностей по управлению сегментацией памяти. Так, уже в микропроцессоре i80386 сняты ограничения на размер сегмента. Он может иметь значение от 1 байта до 4 Гбайт. В нем также сняты ограничения на местоположение границы сегмента. Граница сегмента больше не привязана к границе параграфа, да и само понятие "параграф" к защищенному режиму работы микропроцессора не применяется. Программист в описании сегмента сам определяет уровни привилегий и тип используемого сегмента.
Уровни привилегий назначаются программам с целью не допустить разрушение системных областей некорректными действиями прикладных программ. Некоторые команды выполняются только на нулевом (самом верхнем) уровне привилегий. Выполнение других команд зависит от того, какие уровни привилегий установлены в регистров флагов и при описании сегмента. В любом случае действуют следующие правила вызова сегментов и межсегментных переходов.
1. Возможен переход от сегмента к сегменту, имеющих один и тот же уровень привилегий.
2. Возможно обращение к сегменту данных, имеющему тот же или более низкий уровень привилегий, чем сегмент кода.
3. Если необходимо перейти к сегменту кода, имеющий более высокий уровень привилегий, необходимо использовать вентиль.
Дескрипторные таблицы — служебные структуры данных, содержащие дескрипторы сегментов. В архитектуре x86 есть три вида дескрипторных таблиц:
- Глобальная дескрипторная таблица (англ. Global Descriptor Table, GDT);
- Локальная дескрипторная таблица (англ. Local Descriptor Table, LDT);
- Таблица векторов прерываний (англ. Interrupt Descriptor Table, IDT);
Глобальная дескрипторная таблица одна. Она общая для всех задач. Её размер и расположение в физической памяти определяются регистром GDTR. Размер таблицы не может превышать 8192 дескрипторов, поскольку один дескриптор занимает 8 байт, а лимит в регистре GDTR - двухбайтный и хранит размер таблицы минус один (максимальное значение лимита - 65535), а 8192 x 8 = 65536.
Дескрипторы LDT и сегментов задач (TSS) могут находиться только здесь.
Особенностью GDT является то, что у неё запрещён доступ к первому (с нулевым смещением относительно начала таблицы) дескриптору. Обращение к нему вызывает исключение #GP, что предотвращает обращение к памяти с использованием незагруженного сегментного регистра.
Локальная дескрипторная таблица, в отличие от GDT, LDT может быть много (соответственно количеству задач (потоков), но не обязательно). Каждая задача может иметь свою. На расположение таблицы текущей задачи указывает регистр LDTR.
Размер и расположение LDT в линейной памяти определяются дескриптором LDT из GDT (но это не означает, что размер LDT может быть больше 65536 байт).
Первый дескриптор LDT (№0) использовать можно.
Таблица прерываний глобальна. Размещение в физической памяти определяется регистром IDTR.
При возникновении прерывания (внешнего, аппаратного, или вызванного инструкцией Int):
- из IDT выбирается дескриптор шлюза, соответственно номеру прерывания;
- проверяются условия защиты (права доступа);
- при соблюдении условий защиты выполняется переход на подпрограмму-обработчик этого прерывания
Дескриптор сегмента — служебная структура в памяти, которая определяет сегмент. Длина дескриптора равна восьми байтам.
Структура сегментного дескриптора
База (жёлтые поля, 32 бита) — начало сегмента в линейной памяти
Лимит (красные поля, 20 бит) — (размер сегмента в байтах)-1 (База+Лимит = линейный адрес последнего байта)
Права доступа (синие поля, 12 бит) — флаги, определяющие наличие сегмента в памяти, уровень защиты, тип, разрядность + один пользовательский флаг[1]
Байт прав доступа (AR, англ. Access Rights, биты 8-15 на рисунке):
Бит P определяет доступность сегмента (0 — сегмента нет, 1 — есть). При обращении к сегменту со сброшенным битом P происходит исключение #NP, обработчик которого может загрузить/создать сегмент.
Номер привилегий DPL содержит 2-битный номер (0-3), определяющий, к какому уровню (кольцу) защиты относится этот сегмент.
Тип сегмента (биты 8-12 на рисунке). Старший бит (S) определяет сегмент как системный (S=0) или пользовательский (S=1). Значение прочих бит для системных и пользовательских сегментов описано в таблице:
Типы системных сегментов
№ Биты AR(3210) Описание
0 0000 Зарезервировано
1 0001 Свободный 16-битный TSS
2 0010 LDT
3 0011 Занятый 16-битный TSS
4 0100 16-битный шлюз вызова
5 0101 Шлюз задачи
6 0110 16-битный шлюз прерывания
7 0111 16-битный шлюз ловушки
8 1000 Зарезервировано
9 1001 Свободный 32-битный TSS
A 1010 Зарезервировано
B 1011 Занятый 32-битный TSS
C 1100 32-битный шлюз вызова
D 1101 Зарезервировано
E 1110 32-битный шлюз прерывания
F 1111 32-битный шлюз ловушки
Типы пользовательских сегментов
№ Биты AR(321) Описание
0 000 Сегмент данных только для чтения
2 001 Сегмент данных для чтения/записи
4 010 Сегмент данных только для чтения, растёт вниз
6 011 Сегмент данных для чтения/записи, растёт вниз
8 100 Сегмент кода только для выполнения
A 101 Сегмент кода для выполнения/чтения
C 110 Подчинённый сегмент кода только для выполнения
E 111 Подчинённый сегмент кода для выполнения/чтения
Младший бит байта AR пользовательских сегментов (A, англ. Accessed, бит 8 на рисунке) можно использовать для сбора статистики о сегменте. При первом же обращении к сегменту (чтение, запись, выполнение) он устанавливается процессором в 1.
Флаг гранулярности G определяет лимит сегмента: при G=0 лимит равен значению соответствующего поля в дескрипторе, а при G=1 лимит равен полю дескриптора, умноженному на (212 = 4096). Таким образом при G=0 максимальный размер сегмента 1 МБайт, а при G=14 ГБайт.
Флаг разрядности DB (бит 22 на рисунке) актуален для пользовательских сегментов кода и стека. Определяет разрядность в 16 бит при нулевом и 32 бит при единичном значении.
Зарезервированный флаг (серое поле) должен всегда равняться нулю.
Пользовательский флаг AVL (A, бит 20 на рисунке) отдан операционной системе. Его состояние никак не влияет на работу с сегментом.
- Страничная виртуальная память организует перемещение данных между памятью и диском страницами — частями виртуального адресного пространства, фиксированного и сравнительно небольшого размера.
- Сегментная виртуальная память предусматривает перемещение данных сегментами — частями виртуального адресного пространства произвольного размера, полученными с учетом смыслового значения данных,
- Сегментно-страничная виртуальная память использует двухуровневое деление: виртуальное адресное пространство делится на сегменты, а затем сегменты делятся на страницы. Единицей перемещения данных здесь является страница. Этот способ управления памятью объединяет в себе элементы обоих предыдущих подходов.
Для временного хранения сегментов и страниц на диске отводится либо специальная область, либо специальный файл, которые во многих ОС по традиции продолжают называть областью, или файлом свопинга, хотя перемещение информации между оперативной памятью и диском осуществляется уже не в форме полного замещения одного процесса другим, а частями. Другое популярное название этой области — страничный файл (page file, или paging file). Текущий размер страничного файла является важным параметром, оказывающим влияние на возможности операционной системы: чем больше страничный файл, тем больше приложений может одновременно выполнять ОС (при фиксированном размере оперативной памяти). Однако необходимо понимать, что увеличение числа одновременно работающих приложений за счет увеличения размера страничного файла замедляет их работу, так как значительная часть времени при этом тратится на перекачку кодов и данных из оперативной памяти на диск и обратно. Размер страничного файла в современных ОС является настраиваемым параметром, который выбирается администратором системы для достижения компромисса между уровнем мультипрограммирования и быстродействием системы.
На рис. 5.12 показана схема страничного распределения памяти. Виртуальное адресное пространство каждого процесса делится на части одинакового, фиксированного для данной системы размера, называемые виртуальными страницами (virtual pages). В общем случае размер виртуального адресного пространства процесса не кратен размеру страницы, поэтому последняя страница каждого процесса дополняется фиктивной областью.
Вся оперативная память машины также делится на части такого же размера, называемые физическими страницами (или блоками, или кадрами). Размер страницы выбирается равным степени двойки: 512, 1024, 4096 байт и т. д. Это позволяет упростить механизм преобразования адресов.
Рис. 5.12. Страничное распределение памяти
При создании процесса ОС загружает в оперативную память несколько его виртуальных страниц (начальные страницы кодового сегмента и сегмента данных). Копия всего виртуального адресного пространства процесса находится на диске. Смежные виртуальные страницы не обязательно располагаются в смежных физических страницах. Для каждого процесса операционная система создает таблицу страниц — информационную структуру, содержащую записи обо всех виртуальных страницах процесса.
Запись таблицы, называемая дескриптором страницы, включает следующую информацию:
- номер физической страницы, в которую загружена данная виртуальная страница;
- признак присутствия, устанавливаемый в единицу, если виртуальная страница находится в оперативной памяти;
- признак модификации страницы, который устанавливается в единицу всякий раз, когда производится запись по адресу, относящемуся к данной странице;
- признак обращения к странице, называемый также битом доступа, который устанавливается в единицу при каждом обращении по адресу, относящемуся к данной странице.
Признаки присутствия, модификации и обращения в большинстве моделей современных процессоров устанавливаются аппаратно, схемами процессора при выполнении операции с памятью. Информация из таблиц страниц используется для решения вопроса о необходимости перемещения той или иной страницы между памятью и диском, а также для преобразования виртуального адреса в физический. Сами таблицы страниц, так же как и описываемые ими страницы, размещаются в оперативной памяти. Адрес таблицы страниц включается в контекст соответствующего процесса. При активизации очередного процесса операционная система загружает адрес его таблицы страниц в специальный регистр процессора.
При каждом обращении к памяти выполняется поиск номера виртуальной страницы, содержащей требуемый адрес, затем по этому номеру определяется нужный элемент таблицы страниц, и из него извлекается описывающая страницу информация1. Далее анализируется признак присутствия, и, если данная виртуальная страница находится в оперативной памяти, то выполняется преобразование виртуального адреса в физический, то есть виртуальный адрес заменяется указанным в записи таблицы физическим адресом. Если же нужная виртуальная страница в данный момент выгружена на диск, то происходит так называемое страничное прерывание. Выполняющийся процесс переводится в состояние ожидания, и активизируется другой процесс из очереди процессов, находящихся в состоянии готовности. Параллельно программа обработки страничного прерывания находит на диске требуемую виртуальную страницу (для этого операционная система должна помнить положение вытесненной страницы в страничном файле диска) и пытается загрузить ее в оперативную память. Если в памяти имеется свободная физическая страница, то загрузка выполняется немедленно, если же свободных страниц нет, то на основании принятой в данной системе стратегии замещения страниц решается вопрос о том, какую страницу следует выгрузить из оперативной памяти.
После того как выбрана страница, которая должна покинуть оперативную память, обнуляется ее бит присутствия и анализируется ее признак модификации. Если выталкиваемая страница за время последнего пребывания в оперативной памяти была модифицирована, то ее новая версия должна быть переписана на диск. Если нет, то принимается во внимание, что на диске уже имеется предыдущая копия этой виртуальной страницы, и никакой записи на диск не производится. Физическая страница объявляется свободной. Из соображений безопасности в некоторых системах освобождаемая страница обнуляется, с тем чтобы невозможно было использовать содержимое выгруженной страницы.
1 Здесь не учитывается возможность кэширования записей из таблицы страниц, которая рассматривается несколько позже.
Для хранения информации о положении вытесненной страницы в страничном файле ОС может использовать поля таблицы страниц или же другую системную структуру данных (например, дескриптор сегмента при сегментно-страничной организации виртуальной памяти).
Виртуальный адрес при страничном распределении может быть представлен в виде пары (р, sv), где р — порядковый номер виртуальной страницы процесса (нумерация страниц начинается с 0), a sv — смещение в пределах виртуальной страницы. Физический адрес также может быть представлен в виде пары (n, sf), где n — номер физической страницы, a sf — смещение в пределах физической страницы. Задача подсистемы виртуальной памяти состоит в отображении (р, sv) в (n, sf).
Прежде чем приступить к рассмотрению схемы преобразования виртуального адреса в физический, остановимся на двух базисных свойствах страничной организации.
Первое из них состоит в том, что объем страницы выбирается равным степени двойки — 2k. Из этого следует, что смещение s может быть получено простым отделением k младших разрядов в двоичной записи адреса, а оставшиеся старшие разряды адреса представляют собой двоичную запись номера страницы (при этом неважно, является страница виртуальной или физической). Например, если размер страницы 1 Кбайт (210), то из двоичной записи адреса 50718 = 101 000 111 0012 можно определить, что он принадлежит странице, номер которой в двоичном выражении равен 102 и смещен относительно ее начала на 1 000 111 0012 байт (рис. 5.13).
Рис. 5.13. Двоичное представление адресов
Из рисунка хорошо видно, что номер страницы и ее начальный адрес легко могут быть получены один из другого дополнением или отбрасыванием k нулей, соответствующих смещению. Именно по этой причине часто говорят, что таблица страниц содержит начальный физический адрес страницы в памяти (а не но^ мер физической страницы), хотя на самом деле в таблице указаны только старшие разряды адреса. Начальный адрес страницы называется базовым адресом.
Второе свойство заключается в том, что в пределах страницы непрерывная последовательность виртуальных адресов однозначно отображается в непрерывную последовательность физических адресов, а значит, смещения в виртуальном и физическом адресах sv и sf равны между собой (рис. 5.14).
Рис. 5.14. При отображении виртуального адреса в физический смещение не изменяется
Отсюда следует простая схема преобразования виртуального адреса в физический (рис. 5.15). Младшие разряды физического адреса, соответствующие смещению, получаются переносом такого же количества младших разрядов из виртуального адреса. Старшие разряды физического адреса, соответствующие номеру физической страницы, определяются из таблицы страниц, в которой указывается соответствие виртуальных и физических страниц.
Итак, пусть произошло обращение к памяти по некоторому виртуальному адресу. Аппаратными схемами процессора выполняются следующие действия:
1. Из специального регистра процессора извлекается адрес AT таблицы страниц активного процесса. На основании начального адреса таблицы страниц, номера виртуальной страницы р (старшие разряды виртуального адреса) и длины отдельной записи в таблице страниц L (системная константа) определяется адрес нужного дескриптора в таблице страниц: a=AT+(pxL).
2. Из этого дескриптора извлекается номер соответствующей физической страницы — n.
3. К номеру физической страницы присоединяется смещение s (младшие разряды виртуального адреса).