Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Максимальный режим работы ЦП
Максимальный режим работы ЦП служит для реализации встроенного в него механизма защиты программ и данных друг от друга, что является необходимым условием многозадачной обработки. Основой защищённого режима являются уровни привилегий. Уровень привилегий - это степень использования ресурсов процессора. Всего таких уровней четыре и они имеют номера от 0 до 3. Уровень номер 0 - самый верхний - программе на этом уровне " можно всё". Уровень 1 – следующий в иерархии и запреты, установленные на уровне 0 действуют для уровня 1. Наконец, 3-ий уровень - имеет самый низкий приоритет. Оптимальная схема работы программ по уровням привилегий будет следующая:
Сам по себе уровень привилегий ещё ничего не значит, его нельзя " установить в процессоре". Уровень привилегий применяется как одно их свойств при описании различных объектов, например, программного сегмента и действует при работе только с этим объектом. Уровень привилегий обозначается как " PL" (от Privilege Level) и применяется в сочетаниях, например, IOPL – Input-Output Privilege Level - уровень привилегий ввода-вывода. Первое, с чем сталкивается программа при переходе в защищённый режим - это совершенно другая система адресации памяти. Напомним, что в режиме реальных адресов - для обращения к памяти используется пара 16-разрядных объектов - сегментный регистр и смещение. Адресация памяти в защищенном режиме также производится через сегмент и смещение в сегменте, для чего используется пара регистров, но для описания сегмента используется больше информации, а именно:
Для того, чтобы хранить эту информацию, используется специальная область памяти. Сегмент по-прежнему указывается в сегментном регистре, но теперь в нём хранится номер сегмента из списка определённых сегментов. Этот номер называется селектор. В качестве смещения используется 16- или 32-разрядный регистр. При обращении к памяти, процессор проверяет возможность доступа к сегменту по уровню привилегий, проверяет, не превысил ли адрес предел сегмента и можно ли обращаться к этому сегменту в данном случае (например, запрещена передача управления в сегмент, описывающий данные или стек). Если в результате проверки будет обнаружено нарушение какого-либо условия, то процессор сгенерирует исключение и тем самым обеспечит защиту. Предел сегмента - это максимально допустимое смещение внутри него, таким образом, предел сегмента определяет его размер: размер_сегмента = предел_сегмента + 1. Поскольку значение предела - 20-разрядная величина, это значит, что максимальное значение предела равно 2 20 - 1. Процессор измеряет размер сегмента двумя типами величин: либо байтами, либо страницами. Страница - это блок памяти размером в 4Кб. В описании сегмента можно указать, в каких единицах измеряется сегмент и тогда можно получить два типа сегментов с максимальными размерами: в 1Мб (2 20 байт) или в 4Гб (2 20 страниц = 2 20 * 4Кб = 2 20 * 2 12 = 2 32 байт) Эта способность измерять сегмент либо байтами, либо страницами, называется гранулярность. Значение предела сегмента может быть любым, от 0 до 2 20 - 1, гранулярность устанавливается по усмотрению программиста и может быть либо байтная, либо страничная. Всё это позволяет определять сегменты любого размера - от 0 байт до 4Гб. Сегмент определяется в виде структуры данных, которая называется дескриптор. Размер дескриптора - 8 байт, все дескрипторы хранятся последовательно в специально отведённой области памяти - глобальной дескрипторной таблице. На рис. 5.1. приведен формат структуры дескриптора.
Рис. 5.1. Структура дескриптора Значения предела и адреса сегмента " разбросаны" по всей структуре дескриптора потому, что впервые защищённый режим появился в 16-разрядном процессоре Intel 80286 и для совместимости с ним дескриптор не переделывали, а расширили дополнительными полями (биты с 49 по 63). Практически, в программах формат дескриптора удобнее использовать в следующем виде: descriptor: dw limit_low; младшее слово предела dw address_low; младшее слово адреса db address_hi; 3-й (из четырёх) байт адреса db access_rights; права доступа db limit_hi_and_flags; старшая часть предела и флаги db address_hi; 4-й байт адреса
Байт прав доступа (40-47) имеет следующий формат: 40: A – бит доступа (Accessed) 41-43: Тип сегмента (табл. 5.1) 44: S – бит системного сегмента (System) 45-46: DPL – уровень привелегий (Descriptor Privelege Level) 47: P – бит присутствия (Present) сегмента в ОЗУ Таблица 5.1
Тетрада флагов (52-55) G, D, X, U имеет формат: 52: бит U – пользователь (User) 53: бит X – зарезервирован 54: бит D – размерность (Default size) операндов 55: бит G – бит гранулярности (Granularity) При адресации памяти в защищённом режиме команды ссылаются на сегменты, указывая не их адреса (как в режиме реальных адресов), а описания сегментов (их дескрипторы). Указатель на описание сегмента называется селектор. Другими словами, селектор - это номер дескриптора из таблицы дескрипторов. Адресация производится через пару регистров сегмент: смещение, причём, в качестве сегментного регистра используются обычные CS, SS, DS, ES, FS и GS (последние два появились в ЦП Intel 80386), но в них указывается не адрес сегмента, а селектор дескриптора. Селекторы нужны, по крайней мере, по трём причинам: · Описание сегмента занимает 8 байт и использовать 8-байтные сегментные регистры было бы крайне неэффективно. · Селекторы имеют размер в 16 бит, благодаря чему их можно использовать в сегментных регистрах и обращаться к памяти можно по-прежнему через пару регистров. · Параметры всех сегментов хранятся в отдельной области памяти, доступ к которой имеет только операционная система. Программа, используя селектор, сможет получить о сегменте совсем немного информации и не сможет изменить параметры сегмента, благодаря чему очень удачно реализуется механизм защиты Адрес памяти можно указывать не только через пару регистров, но и в переменных, через пару значений селектор: смещение. Можно было бы определить селектор просто, как номер сегмента, но в защищённом режиме кроме сегментов, дескриптор может определять целый ряд других системных объектов (например, задач), поэтому лучше не упрощать понятия селектора и дескриптора, а привыкнуть к этой терминологии. Селектор имеет следующий формат:
Рис. 5.2. Формат селектора.
Использование селекторов достаточно просто. Для тех дескрипторов, которые будут определены заранее, например, сегментов кода, стека и данных, селекторы подготавливаются как константы и затем используются для загрузки в сегментные регистры. Для дескрипторов, которые программа будет динамически создавать, селекторы придётся определять в переменных и загружать в сегментные регистры из памяти либо конструировать " на ходу", или даже как константы - всё зависит от конкретных условий. Способы использования селекторов и дескрипторов вы можете найти в примерах, которые будут следовать в дальнейших главах. Обращение к дескрипторной таблице процессор производит только в момент загрузки в сегментный регистр нового селектора. После этого содержимое дескриптора копируется в так называемый " теневой регистр", к которому имеет доступ только сам процессор и из которого оно в дальнейшем используется. Любое последующее обращение к сегменту будет происходить с помощью теневого регистра, без обращения к дескрипторной таблице и не потребует лишних тактов на циклы чтения памяти. Правда, эти такты тратятся каждый раз, когда вы загружаете новый селектор, но это не высокая плата за защиту дескрипторов от недозволенного доступа. При загрузке недопустимого значения селектора процессор будет генерировать исключение, даже если вы не обращались через него к памяти. В защищённом режиме работа прерываний происходит следующим образом: Во-вторых, вместо дальних адресов в таблице прерываний используются дескрипторы специальных системных объектов, так называемых шлюзов. Все эти особенности появились в процессоре Intel 80386 и в полном объёме, с небольшими дополнениями, используются во всех 32-разрядных процессорах. Адрес, по которому произойдёт переход на обработчик прерывания, находится в дескрипторе прерывания. Каждому вектору прерыванию соответствует свой дескриптор, все они (до 256) объединяются в специальную таблицу дескрипторов прерываний (IDT) и по формату похожи на дескрипторы сегментов, которые мы рассматривали в разделе " Защищённый режим".
|