Б3В Особенности работы с памятью МП i 386. Механизм дескрипторов. Назначение.
Процессор i386 имеет два режима работы - реальный (real mode) и защищенный (protected mode). В реальном режиме процессор i386 работает как быстрый процессор 8086 с несколько расширенным набором команд. В защищенном режиме процессор i386 может использовать все механизмы 32-х разрядной организации памяти, в том числе механизмы поддержки виртуальной памяти и механизмы переключения задач. Кроме этого, в защищенном режиме для каждой задачи процессор i386 может эмулировать 86 и 286 процессоры, которые в этом случае называются виртуальными процессорами. Таким образом, при многозадачной работе в защищенном режиме процессор i386 работает как несколько виртуальных процессоров, имеющих общую память. Средства поддержки сегментации памяти: Физическое адресное пространство процессора i386 составляет 4 Гбайта, что определяется 32-разрядной шиной адреса. Физическая память является линейной с адресами от 00000000 до FFFFFFFF в шестнадцатеричном представлении. Виртуальный адрес, используемый в программе, представляет собой пару - номер сегмента и смещение внутри сегмента. Смещение хранится в соответствующем поле команды, а номер сегмента - в одном из шести сегментных регистров процессора (CS, SS, DS, ES, FS или GS), каждый из которых является 16-битным. Средства сегментации образуют верхний уровень средств управления виртуальной памятью процессора i386, а средства страничной организации - нижний уровень. Средства страничной организации могут быть как включены, так и выключены (за счет установки определенного бита в управляющем регистре процессора), и в зависимости от этого изменяется смысл преобразования виртуального адреса, которое выполняют средства сегментации. Дескриптор сегмента описывает все характеристики сегмента, необходимые для проверки правильности доступа к нему и нахождения его в физическом адресном пространстве. Процессор i386 поддерживает две таблицы дескрипторов сегментов - глобальную (Global Descriptor Table, GDT) и локальную (Local Descriptor Table, LDT). Глобальная таблица предназначена для описания сегментов операционной системы и сегментов межзадачного взаимодействия, то есть сегментов, которые в принципе могут использоваться всеми процессами, а локальная таблица - для сегментов отдельных задач. Таблица GDT одна, а таблиц LDT должно быть столько, сколько в системе выполняется задач. При этом активной в каждый момент времени может быть только одна из таблиц LDT. Механизм дескрипторов: Дескриптор виртуального сегмента, состоит из нескольких полей, основными из которых являются поле базы - базового 32-разрядного физического адреса начала сегмента, поле размера сегмента и поле прав доступа к сегменту - DPL (Descriptor Privilege Level). Сначала процессор определяет правильность адреса, сравнивая смещение и размер сегмента (в случае выхода за границы сегмента происходит прерывание типа исключение - exсeption). Потом процессор проверяет права доступа задачи к данному сегменту, сравнивая значения полей CPL селектора и DPL дескриптора сегмента. В процессоре i386 мандатный способ определения прав доступа (называемый также механизмом колец защиты), при котором имеется несколько уровней прав доступа, и объекты какого-либо уровня имеют доступ ко всем объектам равного уровня или более низких уровней, но не имеет доступа к объектам более высоких уровней. В процессоре i386 существует четыре уровня прав доступа - от 0-го, который является самым высоким, до 3-го - самого низкого. Очевидно, что операционная система может использовать механизм уровней защиты по своему усмотрению. Однако предполагается, что нулевой уровень будет использован для ядра операционной системы, а третий уровень - для прикладных программ, промежуточные уровни - для утилит и подсистем операционной системы, менее привилегированных, чем ядро. Таким образом, доступ к виртуальному сегменту считается законным, если уровень прав селектора CPL выше или равен уровню прав сегмента DPL (CPL ( DPL). При нарушении прав доступа происходит прерывание, как и в случае несоблюдения границ сегмента. Далее проверяется наличие сегмента в физической памяти по значению бита P дескриптора, и если сегмент отсутствует в физической памяти, то происходит прерывание. При наличии сегмента в памяти вычисляется физический линейный адрес путем сложения базы сегмента и смещения и производится доступ к элементу физической памяти по этому адресу. В случае, когда селектор указывает на таблицу LDT, виртуальный адрес преобразуется в физический аналогичным образом, но для доступа к самой таблице LDT добавляется еще один этап, так как в процессоре регистр LDTR указывает на размещение таблицы LDT не прямо, а косвенно. Сам регистр LDTR имеет размер 16 бит и содержит селектор дескриптора таблицы GDT, который описывает расположение этой таблицы в физической памяти. Поэтому при доступе к элементу физической памяти через таблицу LDT происходит двукратное преобразование виртуального адреса в физический, причем оба раза по описанной выше схеме. Сначала по значению селектора LDTR определяется физический адрес дескриптора из таблицы GDT, описывающего начало расположения таблицы LDT в физической памяти, а затем с помощью селектора задачи вычисляется смещение в таблице LDT и определяется физический адрес нужного дескриптора. Далее процесс аналогичен преобразованию виртуального адреса с помощью таблицы GDT. Дескриптор сегмента содержит еще несколько полей. Однобитное поле G определяет единицу измерения размера сегмента, при G = 0 размер определяется в байтах, и тогда сегмент не может быть больше 64 К, а при G = 1 размер определяется в 4К-байтных страницах, при этом максимальный размер сегмента достигает указанных 4 Гбайт. Поле D определяет тип адресации сегмента: при D = 0 сегмент является 16-битным (для режима эмуляции 16-битных процессоров i86 и i286), а при D = 1 сегмент является 32-битным. Кроме этого в дескрипторе имеется поле типа сегмента, которое в свою очередь делится на несколько полей (рисунок 2.21). Поле S определяет, является ли сегмент системным (S = 1) или пользовательским (S = 0). В свою очередь пользовательские сегменты делятся на сегменты данных (E=0) и сегменты кода (E=1). Для сегмента данных определяются однобитные поля: ED - направления распространения сегмента (ED = 0 для обычного сегмента данных, распространяющегося в сторону увеличения адресов, ED = 1 для стекового сегмента данных, распространяющегося в сторону уменьшения адресов), W - поле разрешения записи в сегмент (при W=1 запись разрешена, при W=0 - запрещена), A - поле доступа к сегменту (1 означает, что после очистки этого поля к сегменту было обращение по чтению или записи, это поле может использоваться операционной системой в ее стратегии замены страниц в оперативной памяти). Для сегмента кода используются однобитные признаки: A - имеет смысл, аналогичный полю A сегмента данных, R - разрешает или запрещает чтение из кодового сегмента, C - бит подчинения, разрешает или запрещает вызов данного кодового сегмента из другого кодового сегмента с более низкими правами доступа. В процессоре i386 существует большое количество системных сегментов, к которым в частности относятся системные сегменты типа LDT, шлюзы вызова подпрограмм и задач и сегменты состояния задачи TSS. Таким образом, для использования чисто сегментного механизма процессора i386 операционной системе необходимо сформировать таблицы GDT и LDT, загрузить их в память (для начала достаточно загрузить только таблицу GDT), загрузить указатели на эти таблицы в регистры GDTR и LDTR и выключить страничную поддержку. Если же операционная система не хочет использовать сегментную организацию виртуальной памяти, то ей достаточно создать таблицу дескрипторов из одного входа (дескриптора) и загрузить базовые значения сегмента в дескриптор. Виртуальное адресное пространство задачи будет состоять из одного сегмента длиной максимум в 4 Гбайта.