Детальное описание клиника стоматология хирургия у нас на сайте. Реставрация сидений автомобиля ремонт ткани сидении.
Организация памяти в процессорах семейства х86 позволяет использовать следующие режимы работы
1. Реальный;
2. Защищенный (сегментации);
3. Страничный;
4. Системного управления.
Реальный режим служит для обеспечения преемственности предыдущих процессоров и программ, а также для некоторых применений.
Защищенный режим служит для того, чтобы дать каждой программе несколько независимых защищенных адресных пространств. Страничный режим используется прежде всего для поддержки виртуальной памяти, т.е. среды, в которой большие адресные пространства моделируются на базе небольшой области оперативной памяти и некоторой дисковой памяти. Разработчики систем могут использовать как оба этих механизма (2 и 3), так и любой из них. При одновременном выполнении нескольких программ для защиты одних программ от влияния на них других программ можно использовать любой механизм.
Режим системного управления прежде всего предназначен для обеспечения перехода процессора в состояние пониженного энергопотребления (будет рассмотрен позднее).
В реальном режиме сегментный регистр содержит непосредственно компоненту адреса (см. рисунок ниже).
Для получения линейного адреса в реальном режиме содержимое сегментного регистра сдвигается на четыре позиции влево (т.е. умножается на 16) и полученный 20-битовый результат складывается с 16-битовым offset (внутрисегментным смещением), вычисленным в соответствии с используемым способом адресации). Эти действия выполняются в процессоре аппаратно блоком формирования адреса и не заметны для программиста. В каждый данный момент времени активны/ доступны программе (для 386+) шесть сегментов (по числу имеющихся в процессоре сегментных регистров).
В реальном режиме сформированный линейный адрес подается непосредственно на физическую адресную шину, т.е. в реальном режиме понятия линейного и физического адресов совпадают. Таким образом, в реальном режиме размер сегмента фиксирован. Максимальный адрес, который можно сформировать по приведенной схеме, равен 0xFFFF0 + 0xFFFF = 0x10FFEF, что дает общее количество адресов 0x10FFF0 = 0x10000 + 0x1000 — 0x10 = 220+216-24.
В реальном режиме содержимое сегментных регистров доступно прикладному программисту и может быть им изменено. Задавая содержимое сегментного регистра, программист может расположить сегмент в физическом адресном пространстве с шагом в 16 байтов.
В защищенном режиме схема вычисления линейного адреса аналогична схеме реального режима в том отношении, что линейный адрес, как и в реальном режиме, получается сложением базового адреса сегмента и значения offset (см. рисунок ниже).
Разница состоит в следующем:
1) Базовый адрес каждого из шести сегментов хранится в не видимом программисту (теневом) "продолжении" соответствующего сегментного регистра и имеет длину 32 бита (4 байта). Теневая часть сегментного регистра имеет длину 8 байтов (64 бита).
2) Логический адрес (offset), как для кода, так и для данных, — имеет длину 32 бита (4 байта).
3) Диапазон значений линейных адресов определяется длиной линейного адреса, которая также составляет 32 бита. Таким образом, базовый адрес задает положение начала сегмента, которое может располагаться в любом месте диапазона линейных адресов.
4) Длина сегмента в защищенном режиме не фиксирована, а задается 20-битовым полем Limit (предел), которое вместе с базовым адресом находится в теневой части сегментного регистра. Длина сегмента может иметь величину от 1 байта до 4 Гбайтов.
5) При выполнении команды процессор сравнивает значение offset с длиной сегмента. Если величина offset превышает размер сегмента (т.е. программа пытается обратиться за границу сегмента), выполнение данной команды останавливается и генерируется прерывание по исключительной ситуации.
6) Если предел не превышен, то вычисляется линейный адрес, и выполнение команды продолжается (и завершается).
Кроме базового адреса (32 бита) и длины сегмента (20 битов), в теневой части каждого сегментного регистра хранится еще ряд характеристик (атрибутов) данного сегмента. Они, в совокупности с базовым адресом и длиной, образуют дескриптор (описатель) сегмента.
Для работы одной программы необходимо определить хотя бы четыре сегмента:
•сегмент кода cs,
•сегмент стека ss,
•два сегмента данных ds и es.
Однако защищенный режим процессоров х86 предназначен для многозадачной работы, когда в памяти ЭВМ одновременно находятся и попеременно (во времени) выполняются несколько программ. Дескрипторы сегментов программ формируются операционной системой в специальных системных структурах данных (дескрипторных таблицах) при подготовке программы к выполнению. Дескрипторные таблицы постоянно хранятся в ОЗУ.
При загрузке ОС вначале работают программы реального режима, котрые создают дескрипторные таблицы и определяют дескрипторы для компонентов ОС, после чего процессор переводится в защищенный режим.
При последующей работе ОС для каждой загружаемой программы определяет несколько сегментов, для каждого сегмента заводит дескриптор и задает для сегмента длину и атрибуты. В ходе попеременной работы нескольких программ часть этих сегментов (или даже все) оказываются загруженными в ОЗУ. Для всех сегментов, загруженных в ОЗУ, операционная система определяет и записывает в дескриптор базовый адрес в линейном адресном пространстве.
Каждая задача, выполняемая на компьютере, может иметь собственную локальную дескрипторную таблицу (Local Descriptor Table, LDT), содержащую описания сегментов (а также и других объектов), доступных только этой задаче. Кроме того, имеется одна глобальная дескрипторная таблица (Global Descriptor Table, GDT), которая содержит описания сегментов, потенциально доступных любой задаче. Каждый из шести сегментных регистров содержит двоичное слово, называемое селектором сегмента (детали см. далее). Селектор сегмента однозначно задает дескриптор сегмента, который используется процессором в данный момент.
Схема трансляции адреса с использованием GDT приведена на рисунке ниже.
Схема трансляции адреса с использованием LDT приведена ниже.
Рассмотрим форматы отдельных элементов. Формат селектора сегмента представлен на рисунке ниже.
Поле INDEX указывает номер дескриптора в таблице дескрипторов. Таблица дескрипторов также представляет собой сегмент размером до 64 Кбайт и может содержать до 8192 элементов.
Поле TI (Table Indicator) выбирает одну из двух дескрипторных таблиц: глобальную GDT или локальную LDT. Каждой задаче могут быть доступны две дескрипторные таблицы, а общее максимальное количество сегментов составляет 16384. (Следует помнить, что часть дескрипторов всегда занята под служебные нужды, сами дескрипторные таблицы тоже представляют собой сегменты, нулевой дескриптор в таблице не допускается использовать, и т.п.)
Двухбитовое поле RPL указывает запрошенный программой уровень привилегий (см. далее) и используется при защите памяти.
Рассмотрим подробнее формат дескриптора сегмента (см. рисунок ниже).
32-битовое поле базового адреса используется при вычислении линейного адреса в соответствии с вышеприведенной схемой.
20-битовое поле предела (Segment Limit) содержит размер сегмента. В зависимости от значения бита G (Granularity), этот размер может быть указан в байтах (при G=0 — максимальный размер сегмента 1Мбайт), либо в 4К-страницах (при G=1 — максимальный размер сегмента 212220 = 4Гбайт). Таким образом, размер сегмента может быть задан в пределах от 1 байта до 4 Гбайт (в отличие от реального режима, где размер сегмента равен 216 байт и фиксирован).
Однобитовый признак размера операнда D/B задает размер операнда по умолчанию, используемого командой при обращении к данному сегменту.
Двухбитовое поле уровень привилегий сегмента DPL (Descriptor Privilege Level) используется механизмом защиты памяти.
Бит присутствия P (Segment Present). Бит присутствия может быть установлен либо сброшен программно, аппаратно только анализируется его состояние. Нулевое значение этого бита при обращении к сегменту вызывает прерывание по исключительной ситуации. Этот бит может быть использован разработчиком операционной системы для "маркировки" сегментов, загруженных в данный момент в физическую память. Этот бит, в частности, может быть использован для органиации виртуальной памяти на уровне замены сегментов.
Бит S равен 0 в дескрипторах сегментов, содержащих код или данные и равен 1 для системных дескрипторов (описывающих сегменты, содержащие дескрипторные таблицы, а также еще ряда других, которые будут рассмотрены позже).
Поле TYPE в дескрипторах системных сегментов обозначает один из 12 возможных типов, а в дескрипторах сегментов кода или данных на этом месте содержатся дополнительные битовые поля, которые будут далее рассмотрены.
Байт, включающий поля P, DPL, S, TYPE носит название байт доступа. Бит 21 старшего слова дескриптора имеет предопределенное значение 0, а бит AVL может использоваться системным ПО как флаг общего назначения.
При рассмотрении механизма формирования линейного адреса при трансляции сегмента возникают следующие вопросы:
1) Откуда берутся дескрипторные таблицы и конкретные значения полей в дескрипторах?
2) Базовые адреса сегментов хранятся в дескрипторах, находящихся в дескрипторной таблице в основной памяти. Если в ходе трансляции сегментов при выполнении каждой команды требуется (возможно неоднократно) обращаться за значениями базовых адресов в основную память, команды в защищенном режиме должны выполняться гораздо медленнее, нежели в реальном. Так ли это?
Ответим на эти вопросы.
Дескрипторные таблицы создаются и заполняются при инициализации операционной среды компонентами операционной системы. Это означает, что, если в реальном режиме процессор способен немедленно после включения выбирать (fetch) и выполнять команды, то для того, чтобы выполнить хотя бы одну команду в защищенном режиме, должна быть создана хотя бы одна дескрипторная таблица (GDT), содержащая хотя бы один дескриптор, описывающий сегмент с кодом программы, а, если в программе содержатся команды обращения к памяти, то требуется наличие еще одного дескриптора, описывающего сегмент данных.
Для ускорения процедуры трансляции сегментов, как уже было отмечено, дескрипторы сегментов, селекторы которых загружены в сегментные регистры, скопированы в невидимые "теневые" 8-байтовые "продолжения" сегментных регистров. Именно из теневых частей (быстро !) извлекается значение базового адреса при трансляции сегмента (см. рисунок ниже).
Когда происходит загрузка дескриптора в теневой регистр? Это происходит при выполнении команд, изменяющих содержимое "обычных" сегментных регистров (команды mov seg_reg, reg; lds; les; lfs, lgs, lss, jmp far, call far, int n,…). При выполнении подобных команд в защищенном режиме, процессор не только помещает новое значение (селектор сегмента) в видимую часть сегментного регистра, но и загружает из соответствующей дескрипторной таблицы восьмибайтовый дескриптор в теневую часть сегментного регистра. Вследствие этого команды, изменяющие содержимое сегментных регистров в защищенном режиме выполняются значительно дольше, чем в реальном.
Как процессор находит дескриптор? Для этого ему надо знать адрес начала (базовый адрес) дескрипторной таблицы и расположение в ней нужного дескриптора (смещение). Индекс дескриптора содержится в селекторе, загружаемом в сегментный регистр. Для хранения базовых адресов дескрипторных таблиц в архитектуру процессоров 386+ было введено несколько новых регистров GDTR, LDTR, IDTR, TR (см. рисунок ниже). Рассмотрим их назначение.
Глобальная дескрипторная таблица хранится в отдельном сегменте памяти. 32-битовый базовый адрес этого сегмента и его 16-битовая длина хранятся в регистре GDTR (Global Descriptor Table Register). Таким образом, максимальная длина таблицы составляет 64 Кбайт, в ней может максимально содержаться 8192 дескриптора.
Локальные дескрипторные таблицы могут создаваться индивидуально для каждой задач. Каждая локальная дескрипторная таблица также хранится в отдельном сегменте, который описывается дескриптором, хранимым в GDT. При запуске данной задачи ее локальная дескрипторная таблица активизируется путем записи селектора ее дескриптора в 16-битовый регистр LDTR (Local Descriptor Table Register). При этом автоматически загружается теневая часть этого регистра, куда переносятся из GDT базовый адрес LDT и ее предел, а также битовые поля атрибутов сегмента.
Регистр IDTR (Interrupt Descriptor Table Register) хранит базовый адрес и длину сегмента, содержащего таблицу дескрипторов прерываний. Дескриптор прерывания выполняет в защищенном режиме те же функции, что вектор прерывания в реальном режиме.
Наконец, регистр задачи TR (Task Register) содержит селектор сегмента задачи TSS (Task State Segment). Его назначение рассматривается в разделе, посвященном поддержке многозадачности.
Рассмотрим более подробно схему обращения к памяти в защищенном режиме.
1) После получения команды на запуск программы операционная система загружает в память первый сегмент кода программы, заполняет в соответствующем дескрипторе поля базы и предела, устанавливает в 1 бит присутствия, а затем передает управление на первую команду программы. При этом перезагружается новым значением селектора сегментный регистр cs. Используя поле index этого селектора, процессор находит в дескрипторной таблице дескриптор соответствующего сегмента кода и переносит его в теневую часть регистра cs.
2) Положение объекта (команды или элемента данных) в памяти задается парой значений seg:offset. Значение seg — селектор сегмента — находится в сегментном регистре. Значение offset для выборки команды берется из счетчика команд, а для элемента данных аппаратно вычисляется процессором в соотвествии с используемым способом адресации. При обращении к памяти, процессор вычисляет линейный адрес. Для этого он складывает значение базового адреса сегмента (из теневой части сегментного регистра) со значением offset и производит обращение к памяти.
3) Если при выполнении команды оказывается, что сегмент, индекс которого используется в команде, отстутствует в памяти (процессор "узнает" об этом, проверяя значение бита присутствия), происходит прерывание по исключительной ситуации. Управление передается операционной системе, и она переносит недостающий сегмент в память с диска, заполняет поля базы и предела в дескрипторе, устанавливает в 1 бит присутствия, а затем (возвратом из прерывания) возвращает управление на ту же команду. Теперь эта команда может выполниться до конца.
4) При выполнении каждой команды аппаратура процессора проверяет выполнение ряда условий (наличие сегмента в памяти — одно из этих условий). Если условие не выполняется, то выполнение команды прекращается и происходит прерывание по исключительной ситуации — это общий принцип срабатывания механизмов защиты.
Сегментный механизм можно использовать для организации виртуальной памяти. Однако это оказалось очень неудобным, так как обычно сегменты имеют разный размер и располагаются в памяти с произвольного адреса. При свопинге (замене) сегментов пространство памяти вследствие этого фрагментируется и, тем самым, расходуется нерационально. Сегментный механизм появился в семействе х86, начиная с модели i80286. Однако работоспособной ОС с виртуальной памятью на базе этого процессора, которая стала бы сколько-нибудь популярной, так и не было разработано. В процессорах 386+ в дополнение к сегментному механизму был разработан страничный механизм трансляции адресов (см далее).
Задаче могут быть доступны две дескрипторные таблицы: GDT и LDT, каждая из которых может содержать до 8192 (213) дескрипторов сегментов. Каждый сегмент может иметь размер до 4 Гбайт (232 байт). Таким образом, ограничение сверху на размер логического адресного пространства составляет 2+213+232=246 байт.
Естественно, такой объем еще весьма долго не сможет целиком поместиться в физической памяти компьютера (для процессоров х86 ее размер ограничен величиной 232 байт). Однако при наличии виртуальной памяти ограничение размера физической памяти лишь замедлит выполнение очень большой программы (за счет потерь на обмен сегментов между памятью и диском).
Для реализации виртуальной памяти очень желательно, чтобы заменяемые блоки имели одинаковый размер и были в памяти выровнены (т.е. лежали с адресов, кратных этому размеру) — это позволит избежать фрагментации памяти при свопинге. Такой механизм имеется в процессорах i386+.
Если включен страничный механизм, то все физическое адресное пространство разбивается на блоки одинакового размера — страницы. В процессорах семейства х86 страницы могут иметь размер 4 кбайт либо 4Мбайт. Существующие операционные системы используют в основном маленькие 4 К-байтные страницы. Дальнейшее рассмотрение идет применительно именно к этому варианту.
Линейный адрес (результат трансляции сегмента) интерпретируется процессором как состоящий из трех частей. Младшие 12 разрядов адреса определяют относительный адрес внутри страницы.
Старшие 20 разрядов линейного адреса (индекс страницы) задают одну из 220 страниц. Это делается с помощью двухступенчатого табличного преобразования. Старшие 20 разрядов линейного адреса интерпретируются как два 10-битовых поля. Разряды 12…20 задают номер дескриптора страницы (Page Table Entry) в таблице страниц (Page Table — см. рисунок ниже).
Дескриптор страницы имеет длину 4 байта. Одна таблица содержит 1024 дескриптора.
Старшие 20 разрядов дескриптора страницы содержат ее базовый адрес. Процессор формирует физический адрес операнда с помощью конкатенации базового адреса (из дескриптора) и внутристраничного смещения (младшая часть линейного адреса).
Табличное преобразование адреса при включенном страничном механизме выполняется один или несколько раз при выполнении каждой команды. Для того, чтобы страничная трансляция присходила быстро, для хранения индексов недавно использовавшихся страниц и их базовых адресов используется небольшая память с ассоциативным доступом — Буфер Ассоциативной Трансляции (Translation LookAside Buffer, TLB), которая обычно выполняется как полностью ассоциативная (Fully Assocciative).
Таблица страниц сама представляет собой 4 Кбайт-страницу. Одна программа использует много страниц (иногда больше, чем 1024), т.е. ей может требоваться больше, чем одна таблица страниц. В схеме трансляции страниц может одновременно использоваться до 1024 таблиц страниц. Каждая таблица страниц (поскольку тоже является страницей) в свою очередь описывается дескриптором в еще одной таблице — в каталоге таблиц страниц (Page Directory).
Старшие десять битов линейного адреса задают индекс дескриптора в каталоге таблиц страниц, т.е. используемую при данном обращении таблицу страниц.
Теперь рассмотрим структуру дескриптора страницы более подробно.
Дескрипторы страниц (любые), кроме базового адреса, содержат еще набор битовых полей, облегчающих реализацию виртуальной памяти и защиты (см. рисунки ниже):
P — бит присутствия страницы в памяти;
R/W — бит разрешения записи на данную страницу — позволяет ограничить доступ к отдельным диапазонам адресов;
U/S — бит уровня привилегий — пользовательская/системная страница;
PWT — алгоритм работы данной страницы с КЭШ-памятью — разрешение "сквозной" записи (Write-Throuhg);
PCD — бит запрета кэширования страницы (Page Cache Disabled);
A — признак того, что к элементам страницы производился доступ (Accessed);
D — признак того, что на страницу производиласть запись (флаг модификации — Dirty);
G — признак "глобальной" (Global) страницы, используется для страниц, постоянно находящихся в памяти (например, чдля ядра операционной системы. Этот признак запрещает удалять дескриптор такой страницы из Буфера Ассоциативной Трансляции.
•Обращение к странице (Р=0): особый случай — страничная ошибка (№=14).
•Вызывается обработчик страничной ошибки.
•Из CR2 линейный адрес страничной ошибки. Из стека — код страничной ошибки.
•Операционная система по таблице ищет нужную страницу на винчестере.
•Из ОЗУ выбрасывается страница (используется бит А и алгоритм LRU). Она записывается при D=1.
•В ОЗУ записывается нужная страница. Повторно выполняется команда. В процессорах Pentium Pro и старше реализован механизм расширения физического адресного пространства. Возможно несколько вариантов размеров страниц (см. таблица ниже).
При этом используется несколько измененный механизм трансляции страниц (см. рисунок ниже).
Размер страницы 4 МБайт выбирается установкой бита PSE в управляющем регистре CR4 и одновременной установкой флага PS (page Size) в дескрипторе страницы (он теперь находится в каталоге таблиц страниц). Линейный адрес в этом режиме содержит два поля:
•индекс одного из 1024 элементов (дескриптора 4М-страницы) в каталоге таблиц страниц,
•22-битовое смещение внутри страницы.
Дескриптор страницы теперь содержит 10 старших битов физического адреса страницы (базу). Таким образом, "большие" страницы выровнены по границе 4 МБайт.
Общий размер адресного пространства снова не превышает 4 Гбайт. В одном каталоге таблиц страниц можно смешивать дескрипторы каталогов таблиц страниц (размером 4К) и дескрипторы 4М-страниц.