Дескрипторы и шлюзы
Таблица дескрипторов прерываний в любой системе - одна. Программ (задач, процедур, приложений и пр.) - много. IDT реализуется на нулевом уровне привилегий и, следовательно, непосредственно к ней обратиться могут только программы, работающие на том же уровне. Для того, чтобы программы с других уровней (1, 2 и 3) могли пользоваться прерываниями, предусмотрены специальные системные объекты - так называемые шлюзы (gates). При вызове прерывания, процессор, прежде, чем передать управление обработчику, "опускается" через шлюз на его уровень привилегий, а после завершения обработки - "поднимается" обратно.
IDT может содержать три типа дескрипторов шлюзов:
· Шлюз задачи
· Шлюз прерывания
· Шлюз ловушки
Шлюзы содержат указатели на обработчики прерываний и права доступа к ним. При переходе через шлюз задачи, процессор производит автоматическое переключение задач, а при переходе через шлюз прерывания или ловушки передаёт управление процедуре в контексте текущей программы. Единственное отличие прерывания от ловушки в том, что при переходе через шлюз прерывания процессор автоматически сбрасывает флаг IF в EFLAGS и тем самым не допускает генерации других прерываний и исключений на время работы обработчика, а для шлюза ловушки - не меняет состояние флага IF. Ловушки используются для отладки программ и поэтому обработка ловушки должна быть прозрачна для внешних прерываний.
Исключения и прерывания работают в основном через два типа шлюзов - задач и прерываний.
Шлюз прерывания запускает обработчик в контексте текущей программы, т.е. просто передаёт управление по адресу, указанному в дескрипторе. Такой подход хорош только в простых операционных системах, когда работают заранее определённые программы, от которых не нужно защищать ядро ОС.
Шлюз задачи является более удобным и универсальным, т.к. позволяет изолировать обработчик от других программ и его рекомендуется применять в системах, где программы потенциально могут нарушить целостность ОС. Шлюз задачи заставляет процессор автоматически переключаться на новую задачу при генерации исключения. Т.к. мультизадачность мы ещё не рассматривали, то обработчики исключений реализуем пока через шлюзы прерываний и ловушек.
Далее приводятся форматы дескрипторов шлюзов:
1. Шлюз задачи.
dw 0
dw TSS_sel ; Селектор TSS
db 0
db access_rights ; Права доступа сегмента TSS
dw 0
Рис. 5.3. Формат шлюза задачи.
Обратите внимание на то, что бит 4 в access_rights, соответствующий биту S в формате дескриптора, равен 0. Это значит, что дескриптор описывает системный объект и биты 0..3 в access_rights определяют тип этого объекта.
Первое и последнее слова (dw) в формате дескриптора содержат 0, т.к. любая задача определяется своим дескриптором, на который и ссылается селектор TSS (подробно о задачах см. в разделе "Мультизадачность").
2. Шлюз прерывания.
dw offset_low ; Младшая часть смещения
dw selector ; Селектор сегмента кода
db 0
db access_rights ; Права доступа
dw offset_hi ; Старшая часть смещения
Шлюз прерывания через селектор и смещение задаёт адрес обработчика прерывания.
Рис. 5.4. Формат шлюза прерывания.
3. Шлюз ловушки.
dw offset_low ; Младшая часть смещения
dw selector ; Селектор сегмента кода
db 0
db access_rights ; Права доступа
dw offset_hi ; Старшая часть смещения
Шлюз ловушки через селектор и смещение задаёт адрес обработчика прерывания.
Рис. 5.5. Формат шлюза ловушки.
Примечание.
D - это размер шлюза: 1 = 32 бита; 0 = 16 бит. Размер шлюза определяет размер стека, используемый процессором по умолчанию. Перед вызовом обработчика, процессор помещает в стек значения регистров CS, EIP, EFLAGS и иногда SS, ESP и dw-код ошибки. Если размер шлюза - 32 бита, то значения размером в 16 бит будут расширены нулями до 32-х.
Исключениями называются прерывания, которые генерирует процессор в ответ на нарушения условий защиты. Повлиять на исключения прикладные программы (работающие на уровне привилегий, выше 0) не могут, замаскировать - тоже. Аппаратный контроль защиты - самый надёжный и 32-разрядные процессоры предоставляют этот сервис в полном объёме.
Исключения делятся на три типа, в зависимости от условий их возникновения:
1. | Ошибка (fault) |
2. | Ловушка (trap) |
3. | Авария (abort) |
Ошибка - это исключение, возникающая в ситуации ошибочных действий программы и подразумевается, что такую ошибку можно исправить. Такой тип исключения позволяет рестарт "виноватой" команды после исправления ситуации, для чего в стеке обработчика адрес возврата из прерывания указывает на команду, вызвавшую исключение. Примером такого исключения может быть исключение неприсутствующего сегмента (прерывание 0Bh), возникающее при попытке обратиться к сегменту, в дескрипторе которого бит P=0. Благодаря этому реализуется механизм виртуальной памяти, в частности, подкачка данных с диска.
Ловушка - это исключение, возникающее сразу после выполнения "отлавливаемой" команды. Это исключение позволяет продолжить выполнение программы со следующей команды (без рестарта "виноватой"). На ловушках строится механизм отладки программ.
Авария - это исключение, которое не позволяет продолжить выполнение прерванной программы и сигнализирует о серьёзных нарушениях целостности системы. Примером аварии служит исключение двойного нарушения (прерывание 8), когда сама попытка обработки одного исключения вызывает другое исключение.
Все дескрипторы прерываний и исключений объединяются в одну таблицу IDT (Interrupt Desriptor Table). Сама IDT может располагаться в памяти по любому адресу и состоять из любого числа дескрипторов в пределах от 0 до 256. В отличие от GDT, нулевой дескриптор в IDT используется нулевым вектором (исключение деления на 0).
Для неиспользуемых векторов бит P дескрипторов должен быть равен 0, тогда при попытке обращения к нему процессор будет генерировать исключение неприсутствующего сегмента и ОС сможет корректно обработать неиспользуемое прерывание. В противном случае, скорее всего, возникнет другое исключение, тип которого заранее предусмотреть невозможно.
Для повышения производительности системы, рекомендуется размещать IDT по адресу, кратному 8. Размер IDT должен быть кратен 8, т.к. она состоит из 8-байтных дескрипторов, а предел, следовательно, на 1 меньше.
Если произойдёт обращение к вектору прерывания, дескриптор которого должен находиться за пределами IDT, то процессор сгенерирует исключение общей защиты.
Параметры IDT (адрес и предел) процессор хранит с специальном 48-разрядном регистре IDTR. Формат этого регистра следующий:
Адрес начала IDT - это тот адрес, по которому вы разместили IDT. Предел таблицы IDT - это максимальное смещение относительно её начала.
Рис. 5.6. Формат регистра IDTR.
Подготовка и запись значения IDTR аналогична действиям для GDTR, поэтому соответствующий пример здесь не приводится.
Для загрузки содержимого IDTR из памяти в регистр используется команда LIDT, для сохранения из регистра в память - SIDT, причём, команда IDTR может выполняться только на нулевом уровне привилегий, а SIDT - на любом. Единственным операндом у обеих команд является адрес 48-разрядной переменной.
Программа, работающая не на 0-м уровне привилегий может получить адрес и предел IDT и только от операционной системы зависит, разрешит ли она доступ непривилегированной программе к IDT.
Контрольные вопросы
1. Сколько существует типов сегментов?
2. Как формируется адрес в реальном режиме?
3. Как формируется адрес в защищенном режиме (сегментная адресация)?
4. Какой сегментный регистр по умолчанию используется при ссылках на данные, находящиеся в стеке?
5. Где хранится селектор и что это такое?
6. Для чего нужен бит пометки "страница находится в памяти"?
7. Что представляет собой таблица векторов прерываний в реальном режиме?
8. Что представляет собой таблица векторов прерываний в защищенном режиме? Как она называется?
9. Для чего нужны GDT и LDT? Где хранятся указатели на их текущие значения?
10. Для чего служит максимальный режим работы ЦП и в чем его отличие от минимального режима?
11. Для чего используется сегментация памяти?
12. Как изменяется адресация памяти в защищенном режиме?
13. Для чего служат уровни привилегий и как они используются?
14. Опишите формат селектора.
15. Какие типы доступа к сегментам Вы знаете?
16. Опишите формат дескриптора в виде структуры, используемой в программах.
17. Что такое дескриптор вектора прерываний и для чего он нужен?
18. Каким образом и для чего используются шлюзы?
19. Какие типы дескрипторов шлюзов Вы знаете?
20. В чем заключается отличие шлюза задачи от шлюза прерывания?
21. Для чего и как используются ловушки?
22. Опишите форматы шлюзов.
23. Какие типы исключений вы знаете?
24. Поясните структуру таблицы IDT.
25. В каких случаях ЦП будет генерировать исключение неприсутствующего сегмента?
Дата добавления: 2015-12-22; просмотров: 2152;