Файл: А. В. Гордеев А. Ю. Молчанов системное программное обеспечение электронный вариант книги издательства Питер СанктПетербург Челябинск юургу каф. Автоматика и управление 2002 2 Предисловие Настоящий учебник.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 12.01.2024
Просмотров: 1022
Скачиваний: 1
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
Рис. 3.5. Сегмент состояния задачи (TSS)
1
В микропроцессорах i80x86 линейным называется адрес, полученный в результате преобразования виртуального адреса формата (S, d) в 32-битовый адрес.
2
EIP (extended instruction pointer) – указатель инструкции (команды).
Поля, определяемые ОС (их количество и со-
став может быть любым)
Адрес карты вво-
да/вывода
LDTR
Сегментные регистры ES, CS, SS, DS, FS, GS
(на каждый регистр отведено по 4 байта. Из
которых используется только 2 младших)
Общие регистры (EAX, ECX, EDX, EBX, ESP,
EBP, ESI, EDI)
Регистры флагов EFLAGS
Указатель команд (регистр EIP)
Привилегированные указатели стеков
Link
68h
60h
48h
28h
24h
20h
0
4
0
15
16
31
Собственно TSS
(108 байтов)
129
Линейный адрес – это одна из форм виртуального адреса. Исходный двоичный виртуальный адрес, вычисляемый в соответствии с используемой адресацией, пре- образуется в линейный. В свою очередь, линейный адрес будет либо равен физиче- скому (если страничное преобразование отключено), либо с помощью страничной трансляции преобразуется в физический адрес. Если же смещение из регистра EIP
превышает размер сегмента кода, то эта аварийная ситуация вызывает прерывание и управление должно передаваться супервизору ОС.
Рассмотренный нами процесс получения линейного адреса проиллюстрирован на рис. 3.6. Стоит отметить, что поскольку межсегментные переходы происходят нечасто, то, как правило, определение линейного адреса заключается только в сравнении значения EIP с полем предела сегмента и в прибавлении смещения к на- чалу сегмента. Все необходимые данные уже находятся в микропроцессоре, и опе- рация получения линейного адреса происходит очень быстро.
Рис. 3.6. Процесс получения линейного адреса команды
Регистр EIP
Искомая команда
Дескриптор
Дескриптор
LDT
GDT
CS
LDTR
GDTR
(адрес (GDT)
Адрес сегмента
Адрес LDT
130
Итак, линейный адрес может считаться физическим адресом, если не включен режим страничной трансляции адресов. Аппаратные средства микропроцессора для поддержки рассмотренного способа двойной трансляции виртуальных адресов в физические явно недостаточны, и при наличии большого количества небольших сегментов приводят к медленной работе. В самом деле, теневой регистр при каж- дом селекторе имеется в единственном экземпляре, и при переходе на другой сег- мент потребуется вновь находить и извлекать соответствующий дескриптор сег- мента, а это требует времени. Страничный же способ трансляции виртуальных ад- ресов, как мы знаем, имеет немало своих достоинств. Поэтому в защищённом ре- жиме работы, при котором всегда действует описанный выше механизм определе- ния линейных адресов, может быть включен ещё и страничный механизм.
Поддержка страничного способа организации виртуальной памяти
При создании микропроцессора i80386 разработчики столкнулись с очень серьезной проблемой в реализации страничного механизма. Дело в том, что мик- ропроцессор имеет широкую шину адреса – 32 бита – и возникает вопрос о раз- биении всего адреса на поле страницы и поле индекса. Если большое количество битов адреса отвести под индекс, то страницы станут очень большими, что повле- чет большие потери и на фрагментацию, и на операции ввода/вывода, связанные с замещением страниц. Хотя количество страниц стало бы при этом меньше, и на- кладные расходы на их поддержание тоже уменьшились бы. Если же размер стра- ницы уменьшить, то большое поле номера страницы привело бы к появлению гро- мадного количества возможных страниц и необходимо было либо вводить какие-то механизмы контроля за номером страницы (с тем, чтобы он не выходил за размеры таблицы страниц), либо создавать эти таблицы максимально возможного размера.
Разработчики пошли по пути, при котором размер страницы все же небольшой (он выбран равным 2 12
= 4096 = 4K), а поле номера страницы величиной в 20 битов, в свою очередь, разбивается на два поля и осуществляется двухэтапная (двухшаго- вая) страничная трансляция.
131
Для описания каждой страницы создается соответствующий дескриптор. Дли- на дескриптора выбрана равной 32 битам: 20 битов линейного адреса определяют номер страницы (по существу – её адрес, поскольку добавление к нему (приписы- вание в качестве младших разрядов) 12 нулей приводит к определению начального адреса страницы), а остальные биты разбиты на следующие поля, которые изобра- жены на рис. 3.7. Как видно, три бита дескриптора зарезервированы для использо- вания системными программистами при разработке подсистемы организации вир- туальной памяти. С этими битами микропроцессор сам не работает.
Рис.3.7. Дескриптор страницы
Прежде всего, микропроцессор анализирует самый младший бит дескриптора
– бит присутствия, ибо если поле present равно нулю, то это означает отсутствие данной страницы в оперативной памяти, и такая ситуация влечет прерывание в ра- боте процессора с передачей управления соответствующей программе, которая должна будет загрузить затребованную страницу. Бит dirty – «грязный» – пред- назначен для отметки, что данную страницу модифицировали и при замещении этого страничного кадра следующим её необходимо сохранить во внешней памяти.
Бит обращения (access) свидетельствует о том, что к данной таблице или странице осуществлялся доступ. Он используется для определения страницы, которая будет участвовать в замещении при использовании дисциплин LRU или LFU. Наконец,
первый и второй биты используются для защиты памяти.
Старшие 10 битов линейного адреса определяют номер таблицы страниц (page table entry, РТЕ), из которой посредством вторых 10 битов линейного адреса вы- бирается соответствующий дескриптор виртуальной страницы. И уже из этого де- скриптора выбирается номер физической страницы, если данная виртуальная стра- ница отображена сейчас на оперативную память. Эта схема определения фи- зического адреса по линейному изображена на рис. 3.8.
Адрес таблицы страниц
или адрес страничного
кадра
Для
ОС
00
Бит
Dirty
Бит
Access
00
User/
Supervisor
Read/
Write
Present
0
1
2
3
4
5
6
7
8
9
11
12
31
132
Первая таблица, которую мы индексируем первыми (старшими) 10 битами ли- нейного адреса, названа таблицей каталогов таблиц страниц (page directory entry,
PDE). Её адрес в оперативной памяти определяется старшими 20 битами управ- ляющего регистра CR3.
Рис. 3.8. Трансляция линейного адреса в микропроцессорах i80x86
Каждая из таблиц PDE и РТЕ состоит из 1024 элементов (2 10
= l024). В свою очередь, каждый элемент (дескриптор страницы) имеет длину 4 байта (32 бита), по- этому размер этих таблиц как раз соответствует размеру страницы.
Оценим теперь эту двухшаговую схему трансляции с позиций расхода памяти.
Каждый дескриптор описывает страницу размером 4 Кбайт. Следовательно, одна таблица страниц, содержащая 1024 дескриптора, описывает пространство памяти в
4 Мбайт. Если наша задача пользуется виртуальным адресным пространством, на- пример, в 50 Мбайт (предположим, что речь идёт о некотором графическом редак- торе, который обрабатывает изображение, состоящее из большого количества пик-
Линейный адрес
31 23
21 12
11 0
DTE
1023
31 12
11 0
0
PTE
1023
31 12
11 0
0
31 12
11 0
||
Физический адрес
133
селов
1
), то для описания этой памяти необходимо иметь 14 страниц, содержащих таблицы РТЕ. Кроме этого, нам потребуется для этой задачи ещё одна таблица PDE
(тоже размером в одну страницу), в которой 14 дескрипторов будут указывать на местонахождение упомянутых таблиц РТЕ. Остальные дескрипторы PDE могут быть не задействованы. Итого, для описания 50 Мбайт адресного пространства за- дачи потребуется всего 15 страниц, то есть 60 Кбайт памяти, что можно считать приемлемым.
Если бы не был использован такой двухшаговый механизм трансляции, то по- тери памяти на описание адресного пространства могли бы составить 4(Кбайт)
«2 10
= 4 (Мбайт)! Очевидно, что это уже неприемлемое решение.
Итак, микропроцессор для каждой задачи, для которой у него есть TSS, позво- ляет иметь таблицу PDE и некоторое количество РТЕ. Поскольку это дает возмож- ность адресоваться к любому байту из 2 32
, а шина адреса как раз и позволяет ис- пользовать физическую память с таким объёмом, то можно как бы отказаться от сегментного способа адресации. Другими словами, если считать, что задача состо- ит из одного единственного сегмента, который, в свою очередь, разбит на страни- цы, то фактически мы получаем только один страничный механизм работы с вир- туальной памятью. Этот подход получил название «плоской памяти». При исполь- зовании плоской модели памяти упрощается создание и операционных систем, и систем программирования. Кроме этого, уменьшаются расходы памяти для под- держки системных информационных структур. Поэтому в абсолютном большинст- ве современных 32-разрядных ОС, создаваемых для микропроцессоров i80x86, ис- пользуется плоская модель памяти.
Режим виртуальных машин для исполнения приложений реального режима
Разработчики рассматриваемого семейства микропроцессоров в своем стрем- лении обеспечить максимально возможную совместимость архитектуры пошли не только на то, чтобы обеспечить возможность программам, созданным для первых
1
Напомним, что термин пиксел происходит от английского picture element (графический элемент). Множество пик- селов образуют изображение.
134 16-разрядных ПК, без проблем выполняться на компьютерах с более поздними мо- делями микропроцессоров за счёт введения реального режима работы. Они также обеспечили возможность выполнения 16-разрядных приложений реального режима при условии, что сам процессор при этом функционирует в защищённом режиме работы и операционная система, используя соответствующие аппаратные средства микропроцессора, организует мультипрограммный (мультизадачный) режим. Дру- гими словами, микропроцессоры i80x86 поддерживают возможность создания опе- рационных сред реального режима при работе микропроцессора в защищённом режиме. Если условно назвать 16-разрядные приложения DOS-приложениями (по- скольку в абсолютном большинстве случаев это именно так), то можно сказать, что введена поддержка для организации виртуальных DOS-машин, работающих вместе с обычными 32-битовыми приложениями защищённого режима. Это даже нашло отражение в названии режима работы микропроцессоров i80x86 – режим виртуаль- ного процессора i8086, иногда (для краткости) его называют режимом V86 или просто виртуальным режимом, – при котором в защищённом режиме работы мо- жет исполняться код DOS-приложения. Мультизадачность при выполнении не- скольких программ реального режима будет поддержана аппаратными средствами защищённого режима.
Переход в виртуальный режим осуществляется посредством изменения бита
VM (virtual mode) в регистре EFLAGS. Когда процессор находится в виртуальном режиме, для адресации памяти используется схема реального режима работы –
(сегмент: смещение) с размером сегментов до 64 Кбайт, которые могут распола- гаться в адресном пространстве размером в 1 Мбайт, однако полученные адреса считаются не физическими, а линейными. В результате применения страничной трансляции осуществляется отображение виртуального адресного пространства 16- битового приложения на физическое адресное пространство. Это позволяет орга- низовать параллельное выполнение нескольких задач, разработанных для реально- го режима, да ещё и совместно с обычными 32-битовыми приложениями, требую- щих защищённого режима работы. Естественно, что для обработки прерываний,
возникающих при выполнении 16-битовых приложений в виртуальном режиме,
135
процессор возвращается из этого режима в обычный защищённый режим. В про- тивном случае невозможно было бы организовать полноценную виртуальную ма- шину. Очевидно, что обработчики прерываний для виртуальной машины должны эмулировать работу подсистемы прерываний процессора i8086. Другими словами,
прерывания отображаются в операционную систему, работающую в защищённом режиме, и уже основная ОС моделирует работу операционной среды выполняемого приложения.
Вопрос, связанный с операциями ввода/вывода, которые недоступны для обычных приложений (см. следующую главу), решается аналогично. При попытке выполнить недопустимые команды ввода/вывода возникают прерывания, и не- обходимые операции выполняются операционной системой, хотя задача об этом и
«не подозревает». При выполнении команд IN, OUT, INS, OUTS, CLI, STI процес- сор, находящийся в виртуальном режиме и исполняющий код на уровне привиле- гий третьего (самого нижнего) кольца защиты, за счёт возникающих вследствие этого прерываний переводится на выполнение высоко привилегированного кода операционной системы.
Таким образом, ОС может полностью виртуализировать ресурсы компьютера:
и аппаратные
1
, и программные, создавая иную полноценную операционную среду;
при существовании так называемых нативных приложений, создаваемых по собст- венным спецификациям данной ОС. Очень важным моментом для организации полноценной виртуальной машины является реализация виртуализации не только программных, но и аппаратных ресурсов. Так, например, в ОС Windows NT эта за- дача выполнена явно неудачно, тогда как в OS/2 имеется полноценная виртуальная машина как для DOS-приложений, так и для приложений, работающих в среде спецификаций Win 16. Правда, в последнее время это уже перестало быть актуаль- ным, поскольку появилось большое количество приложений, работающих по спе- цификациям Win32 API.
1
Речь идёт о памяти, портах ввода/вывода, системе обработки прерываний и других архитектурных особенностях.
136
Защита адресного пространства задач
Для возможности создания надёжных мультипрограммных ОС в процессорах семейства i80x86 имеется несколько механизмов защиты. Это и разделение адрес- ных пространств задач, и введение уровней привилегий для сегментов кода и сег- ментов данных. Все это позволяет обеспечить как защиту задач друг от друга, так и защиту самой операционной системы от прикладных задач, защиту одной части
ОС от других её компонентов, защиту самих задач от некоторых своих собствен- ных ошибок.
Защита адресного пространства задач осуществляется относительно легко за счёт того, что каждая задача может иметь свое собственное локальное адресное пространство. Операционная система должна корректно манипулировать табли- цами трансляции сегментов (дескрипторными таблицами) и таблицами трансляции страничных кадров. Сами таблицы дескрипторов как сегменты данных (а соответ- ственно, в свою очередь, и как страничные кадры) относятся к адресному про- странству операционной системы и имеют соответствующие привилегии доступа;
исправлять их задачи не могут. Этими информационными структурами процессор пользуется сам, на аппаратном уровне, без возможности их читать и редактировать из пользовательских приложений. Если используется модель плоской памяти, то возможность микропроцессора контролировать обращения к памяти только внутри текущего сегмента фактически не используется, и остается в основном только ме- ханизм отображения страничных кадров. Выход за пределы страничного кадра не- возможен, поэтому фиксируется только выход за пределы своего сегмента. В этом случае приходится полагаться только на систему программирования, которая должна корректно распределять программные модули в пределах единого неструк- турированного адресного пространства задачи. Поэтому при создании многопо- точных приложений, когда каждая задача (в данном случае – поток) может испор- тить адресное пространство другой задачи, эта проблема становится очень слож- ной, особенно если не использовать системы программирования на языках высоко- го уровня.
137
Однако для организации взаимодействия задач, имеющих разные виртуальные адресные пространства, необходимо, как мы уже говорили, иметь общее адресное пространство. И здесь, для обеспечения защиты самой ОС, а значит, и повышения надёжности всех вычислений, используется механизм защиты сегментов с помо- щью уровней привилегий.
Уровни привилегий для защиты адресного пространства задач
Для того чтобы запретить пользовательским задачам модифицировать области памяти, принадлежащие самой ОС, необходимо иметь специальные средства. Од- ного разграничения адресных пространств через механизм сегментов мало, ибо можно указывать различные значения адреса начала сегмента и тем самым полу- чать доступ к чужим сегментам. Другими словами, необходимо в явном виде раз- граничивать системные сегменты данных и кода от сегментов, принадлежащих пользовательским программам. Поэтому были введены два основных режима рабо- ты процессора: пользователя и супервизора. Большинство современных процессо- ров имеют по крайней мере два этих режима. Так, в режиме супервизора програм- ма может выполнять все действия и иметь доступ по любым адресам, тогда как в
пользовательском режиме должны быть ограничения, с тем, чтобы обнаруживать и пресекать запрещенные действия, перехватывая их и передавая управление су- первизору ОС. Часто в пользовательском режиме запрещается выполнение команд ввода/вывода и некоторых других, чтобы гарантировать, что только ОС выполняет эти операции. Можно сказать, что эти два режима имеют разные уровни привиле- гий.
В микропроцессорах i80x86 имеются не два, а четыре уровня привилегий. Час- то уровни привилегий называют кольцами защиты, поскольку это иногда помогает объяснить принцип действия самого механизма; поэтому говорят, что некоторый программный модуль «исполняется в кольце защиты с таким-то номером». Для указания уровня привилегий используются два бита, поэтому код 00 обозначает самый высший уровень, а код 11
(2)
(=3) – самый низший. Самый высокий уровень привилегий предназначен для операционной системы (прежде всего, для ядра ОС),
138
самый низкий – для прикладных задач пользователя. Промежуточные уровни при- вилегий введены для большей свободы системных программистов в организации надёжных вычислений при создании ОС и иного системного ПО. Предполагалось,
что уровень с номером (кодом) 1 может быть использован, например, для систем- ного сервиса – программ обслуживания аппаратуры, драйверов, работающих с пор- тами ввода/вывода. Уровень привилегий с кодом 2 может быть использован для создания пользовательских интерфейсов, систем управления базами данных и т. п.,
то есть для реализации специальных системных функций, которые по отношению к супервизору ОС ведут себя как обычные приложения. Так, например, система OS/2
использует три уровня привилегий: с нулевым уровнем привилегий исполняется код самой ОС, на втором уровне исполняются системные процедуры подсистемы ввода/вывода, на третьем уровне исполняются прикладные задачи пользователей.
Однако чаще всего на практике используются только два уровня – нулевой и тре- тий. Таким образом, упомянутый режим супервизора для микропроцессоров i80x86
соответствует выполнению кода с уровнем привилегий 0 (его обозначают так:
PL0 1
). Подводя итог, можно констатировать, что именно уровень привилегий задач определяет, какие команды в них можно использовать и какое подмножество сег- ментов и/или страниц в их адресном пространстве они могут обрабатывать.
Основными системными объектами, которыми манипулирует процессор при работе в защищённом режиме, являются дескрипторы. Дескрипторы сегментов со- держат информацию об уровне привилегий соответствующего сегмента кода или данных. Уровень привилегии исполняющейся задачи определяется значением поля привилегий, находящегося в дескрипторе её текущего кодового сегмента. Напом- ним, что в каждом дескрипторе сегмента (см. рис.3.3) имеется поле DPL в байте прав доступа, которое и определяет уровень привилегии связанного с ним сегмен- та. Таким образом, поле DPL текущего сегмента кода становится полем CPL. При обращении к какому-нибудь сегменту в соответствующем селекторе указывается запрашиваемый уровень привилегий RPL
2
(см. рис. 3.4).
1
PL (privilege level) – уровень привилегий.
2
RPL (requested privilege level) – запрашиваемый уровень привилегий. Поле RPL определяется программистом (сис- темой программирования). В отличие от поля DPL поле RPL легко может быть изменено.
1
В микропроцессорах i80x86 линейным называется адрес, полученный в результате преобразования виртуального адреса формата (S, d) в 32-битовый адрес.
2
EIP (extended instruction pointer) – указатель инструкции (команды).
Поля, определяемые ОС (их количество и со-
став может быть любым)
Адрес карты вво-
да/вывода
LDTR
Сегментные регистры ES, CS, SS, DS, FS, GS
(на каждый регистр отведено по 4 байта. Из
которых используется только 2 младших)
Общие регистры (EAX, ECX, EDX, EBX, ESP,
EBP, ESI, EDI)
Регистры флагов EFLAGS
Указатель команд (регистр EIP)
Привилегированные указатели стеков
Link
68h
60h
48h
28h
24h
20h
0
4
0
15
16
31
Собственно TSS
(108 байтов)
129
Линейный адрес – это одна из форм виртуального адреса. Исходный двоичный виртуальный адрес, вычисляемый в соответствии с используемой адресацией, пре- образуется в линейный. В свою очередь, линейный адрес будет либо равен физиче- скому (если страничное преобразование отключено), либо с помощью страничной трансляции преобразуется в физический адрес. Если же смещение из регистра EIP
превышает размер сегмента кода, то эта аварийная ситуация вызывает прерывание и управление должно передаваться супервизору ОС.
Рассмотренный нами процесс получения линейного адреса проиллюстрирован на рис. 3.6. Стоит отметить, что поскольку межсегментные переходы происходят нечасто, то, как правило, определение линейного адреса заключается только в сравнении значения EIP с полем предела сегмента и в прибавлении смещения к на- чалу сегмента. Все необходимые данные уже находятся в микропроцессоре, и опе- рация получения линейного адреса происходит очень быстро.
Рис. 3.6. Процесс получения линейного адреса команды
Регистр EIP
Искомая команда
Дескриптор
Дескриптор
LDT
GDT
CS
LDTR
GDTR
(адрес (GDT)
Адрес сегмента
Адрес LDT
130
Итак, линейный адрес может считаться физическим адресом, если не включен режим страничной трансляции адресов. Аппаратные средства микропроцессора для поддержки рассмотренного способа двойной трансляции виртуальных адресов в физические явно недостаточны, и при наличии большого количества небольших сегментов приводят к медленной работе. В самом деле, теневой регистр при каж- дом селекторе имеется в единственном экземпляре, и при переходе на другой сег- мент потребуется вновь находить и извлекать соответствующий дескриптор сег- мента, а это требует времени. Страничный же способ трансляции виртуальных ад- ресов, как мы знаем, имеет немало своих достоинств. Поэтому в защищённом ре- жиме работы, при котором всегда действует описанный выше механизм определе- ния линейных адресов, может быть включен ещё и страничный механизм.
Поддержка страничного способа организации виртуальной памяти
При создании микропроцессора i80386 разработчики столкнулись с очень серьезной проблемой в реализации страничного механизма. Дело в том, что мик- ропроцессор имеет широкую шину адреса – 32 бита – и возникает вопрос о раз- биении всего адреса на поле страницы и поле индекса. Если большое количество битов адреса отвести под индекс, то страницы станут очень большими, что повле- чет большие потери и на фрагментацию, и на операции ввода/вывода, связанные с замещением страниц. Хотя количество страниц стало бы при этом меньше, и на- кладные расходы на их поддержание тоже уменьшились бы. Если же размер стра- ницы уменьшить, то большое поле номера страницы привело бы к появлению гро- мадного количества возможных страниц и необходимо было либо вводить какие-то механизмы контроля за номером страницы (с тем, чтобы он не выходил за размеры таблицы страниц), либо создавать эти таблицы максимально возможного размера.
Разработчики пошли по пути, при котором размер страницы все же небольшой (он выбран равным 2 12
= 4096 = 4K), а поле номера страницы величиной в 20 битов, в свою очередь, разбивается на два поля и осуществляется двухэтапная (двухшаго- вая) страничная трансляция.
131
Для описания каждой страницы создается соответствующий дескриптор. Дли- на дескриптора выбрана равной 32 битам: 20 битов линейного адреса определяют номер страницы (по существу – её адрес, поскольку добавление к нему (приписы- вание в качестве младших разрядов) 12 нулей приводит к определению начального адреса страницы), а остальные биты разбиты на следующие поля, которые изобра- жены на рис. 3.7. Как видно, три бита дескриптора зарезервированы для использо- вания системными программистами при разработке подсистемы организации вир- туальной памяти. С этими битами микропроцессор сам не работает.
Рис.3.7. Дескриптор страницы
Прежде всего, микропроцессор анализирует самый младший бит дескриптора
– бит присутствия, ибо если поле present равно нулю, то это означает отсутствие данной страницы в оперативной памяти, и такая ситуация влечет прерывание в ра- боте процессора с передачей управления соответствующей программе, которая должна будет загрузить затребованную страницу. Бит dirty – «грязный» – пред- назначен для отметки, что данную страницу модифицировали и при замещении этого страничного кадра следующим её необходимо сохранить во внешней памяти.
Бит обращения (access) свидетельствует о том, что к данной таблице или странице осуществлялся доступ. Он используется для определения страницы, которая будет участвовать в замещении при использовании дисциплин LRU или LFU. Наконец,
первый и второй биты используются для защиты памяти.
Старшие 10 битов линейного адреса определяют номер таблицы страниц (page table entry, РТЕ), из которой посредством вторых 10 битов линейного адреса вы- бирается соответствующий дескриптор виртуальной страницы. И уже из этого де- скриптора выбирается номер физической страницы, если данная виртуальная стра- ница отображена сейчас на оперативную память. Эта схема определения фи- зического адреса по линейному изображена на рис. 3.8.
Адрес таблицы страниц
или адрес страничного
кадра
Для
ОС
00
Бит
Dirty
Бит
Access
00
User/
Supervisor
Read/
Write
Present
0
1
2
3
4
5
6
7
8
9
11
12
31
132
Первая таблица, которую мы индексируем первыми (старшими) 10 битами ли- нейного адреса, названа таблицей каталогов таблиц страниц (page directory entry,
PDE). Её адрес в оперативной памяти определяется старшими 20 битами управ- ляющего регистра CR3.
Рис. 3.8. Трансляция линейного адреса в микропроцессорах i80x86
Каждая из таблиц PDE и РТЕ состоит из 1024 элементов (2 10
= l024). В свою очередь, каждый элемент (дескриптор страницы) имеет длину 4 байта (32 бита), по- этому размер этих таблиц как раз соответствует размеру страницы.
Оценим теперь эту двухшаговую схему трансляции с позиций расхода памяти.
Каждый дескриптор описывает страницу размером 4 Кбайт. Следовательно, одна таблица страниц, содержащая 1024 дескриптора, описывает пространство памяти в
4 Мбайт. Если наша задача пользуется виртуальным адресным пространством, на- пример, в 50 Мбайт (предположим, что речь идёт о некотором графическом редак- торе, который обрабатывает изображение, состоящее из большого количества пик-
Линейный адрес
31 23
21 12
11 0
DTE
1023
31 12
11 0
0
PTE
1023
31 12
11 0
0
31 12
11 0
||
Физический адрес
133
селов
1
), то для описания этой памяти необходимо иметь 14 страниц, содержащих таблицы РТЕ. Кроме этого, нам потребуется для этой задачи ещё одна таблица PDE
(тоже размером в одну страницу), в которой 14 дескрипторов будут указывать на местонахождение упомянутых таблиц РТЕ. Остальные дескрипторы PDE могут быть не задействованы. Итого, для описания 50 Мбайт адресного пространства за- дачи потребуется всего 15 страниц, то есть 60 Кбайт памяти, что можно считать приемлемым.
Если бы не был использован такой двухшаговый механизм трансляции, то по- тери памяти на описание адресного пространства могли бы составить 4(Кбайт)
«2 10
= 4 (Мбайт)! Очевидно, что это уже неприемлемое решение.
Итак, микропроцессор для каждой задачи, для которой у него есть TSS, позво- ляет иметь таблицу PDE и некоторое количество РТЕ. Поскольку это дает возмож- ность адресоваться к любому байту из 2 32
, а шина адреса как раз и позволяет ис- пользовать физическую память с таким объёмом, то можно как бы отказаться от сегментного способа адресации. Другими словами, если считать, что задача состо- ит из одного единственного сегмента, который, в свою очередь, разбит на страни- цы, то фактически мы получаем только один страничный механизм работы с вир- туальной памятью. Этот подход получил название «плоской памяти». При исполь- зовании плоской модели памяти упрощается создание и операционных систем, и систем программирования. Кроме этого, уменьшаются расходы памяти для под- держки системных информационных структур. Поэтому в абсолютном большинст- ве современных 32-разрядных ОС, создаваемых для микропроцессоров i80x86, ис- пользуется плоская модель памяти.
Режим виртуальных машин для исполнения приложений реального режима
Разработчики рассматриваемого семейства микропроцессоров в своем стрем- лении обеспечить максимально возможную совместимость архитектуры пошли не только на то, чтобы обеспечить возможность программам, созданным для первых
1
Напомним, что термин пиксел происходит от английского picture element (графический элемент). Множество пик- селов образуют изображение.
134 16-разрядных ПК, без проблем выполняться на компьютерах с более поздними мо- делями микропроцессоров за счёт введения реального режима работы. Они также обеспечили возможность выполнения 16-разрядных приложений реального режима при условии, что сам процессор при этом функционирует в защищённом режиме работы и операционная система, используя соответствующие аппаратные средства микропроцессора, организует мультипрограммный (мультизадачный) режим. Дру- гими словами, микропроцессоры i80x86 поддерживают возможность создания опе- рационных сред реального режима при работе микропроцессора в защищённом режиме. Если условно назвать 16-разрядные приложения DOS-приложениями (по- скольку в абсолютном большинстве случаев это именно так), то можно сказать, что введена поддержка для организации виртуальных DOS-машин, работающих вместе с обычными 32-битовыми приложениями защищённого режима. Это даже нашло отражение в названии режима работы микропроцессоров i80x86 – режим виртуаль- ного процессора i8086, иногда (для краткости) его называют режимом V86 или просто виртуальным режимом, – при котором в защищённом режиме работы мо- жет исполняться код DOS-приложения. Мультизадачность при выполнении не- скольких программ реального режима будет поддержана аппаратными средствами защищённого режима.
Переход в виртуальный режим осуществляется посредством изменения бита
VM (virtual mode) в регистре EFLAGS. Когда процессор находится в виртуальном режиме, для адресации памяти используется схема реального режима работы –
(сегмент: смещение) с размером сегментов до 64 Кбайт, которые могут распола- гаться в адресном пространстве размером в 1 Мбайт, однако полученные адреса считаются не физическими, а линейными. В результате применения страничной трансляции осуществляется отображение виртуального адресного пространства 16- битового приложения на физическое адресное пространство. Это позволяет орга- низовать параллельное выполнение нескольких задач, разработанных для реально- го режима, да ещё и совместно с обычными 32-битовыми приложениями, требую- щих защищённого режима работы. Естественно, что для обработки прерываний,
возникающих при выполнении 16-битовых приложений в виртуальном режиме,
135
процессор возвращается из этого режима в обычный защищённый режим. В про- тивном случае невозможно было бы организовать полноценную виртуальную ма- шину. Очевидно, что обработчики прерываний для виртуальной машины должны эмулировать работу подсистемы прерываний процессора i8086. Другими словами,
прерывания отображаются в операционную систему, работающую в защищённом режиме, и уже основная ОС моделирует работу операционной среды выполняемого приложения.
Вопрос, связанный с операциями ввода/вывода, которые недоступны для обычных приложений (см. следующую главу), решается аналогично. При попытке выполнить недопустимые команды ввода/вывода возникают прерывания, и не- обходимые операции выполняются операционной системой, хотя задача об этом и
«не подозревает». При выполнении команд IN, OUT, INS, OUTS, CLI, STI процес- сор, находящийся в виртуальном режиме и исполняющий код на уровне привиле- гий третьего (самого нижнего) кольца защиты, за счёт возникающих вследствие этого прерываний переводится на выполнение высоко привилегированного кода операционной системы.
Таким образом, ОС может полностью виртуализировать ресурсы компьютера:
и аппаратные
1
, и программные, создавая иную полноценную операционную среду;
при существовании так называемых нативных приложений, создаваемых по собст- венным спецификациям данной ОС. Очень важным моментом для организации полноценной виртуальной машины является реализация виртуализации не только программных, но и аппаратных ресурсов. Так, например, в ОС Windows NT эта за- дача выполнена явно неудачно, тогда как в OS/2 имеется полноценная виртуальная машина как для DOS-приложений, так и для приложений, работающих в среде спецификаций Win 16. Правда, в последнее время это уже перестало быть актуаль- ным, поскольку появилось большое количество приложений, работающих по спе- цификациям Win32 API.
1
Речь идёт о памяти, портах ввода/вывода, системе обработки прерываний и других архитектурных особенностях.
136
Защита адресного пространства задач
Для возможности создания надёжных мультипрограммных ОС в процессорах семейства i80x86 имеется несколько механизмов защиты. Это и разделение адрес- ных пространств задач, и введение уровней привилегий для сегментов кода и сег- ментов данных. Все это позволяет обеспечить как защиту задач друг от друга, так и защиту самой операционной системы от прикладных задач, защиту одной части
ОС от других её компонентов, защиту самих задач от некоторых своих собствен- ных ошибок.
Защита адресного пространства задач осуществляется относительно легко за счёт того, что каждая задача может иметь свое собственное локальное адресное пространство. Операционная система должна корректно манипулировать табли- цами трансляции сегментов (дескрипторными таблицами) и таблицами трансляции страничных кадров. Сами таблицы дескрипторов как сегменты данных (а соответ- ственно, в свою очередь, и как страничные кадры) относятся к адресному про- странству операционной системы и имеют соответствующие привилегии доступа;
исправлять их задачи не могут. Этими информационными структурами процессор пользуется сам, на аппаратном уровне, без возможности их читать и редактировать из пользовательских приложений. Если используется модель плоской памяти, то возможность микропроцессора контролировать обращения к памяти только внутри текущего сегмента фактически не используется, и остается в основном только ме- ханизм отображения страничных кадров. Выход за пределы страничного кадра не- возможен, поэтому фиксируется только выход за пределы своего сегмента. В этом случае приходится полагаться только на систему программирования, которая должна корректно распределять программные модули в пределах единого неструк- турированного адресного пространства задачи. Поэтому при создании многопо- точных приложений, когда каждая задача (в данном случае – поток) может испор- тить адресное пространство другой задачи, эта проблема становится очень слож- ной, особенно если не использовать системы программирования на языках высоко- го уровня.
137
Однако для организации взаимодействия задач, имеющих разные виртуальные адресные пространства, необходимо, как мы уже говорили, иметь общее адресное пространство. И здесь, для обеспечения защиты самой ОС, а значит, и повышения надёжности всех вычислений, используется механизм защиты сегментов с помо- щью уровней привилегий.
Уровни привилегий для защиты адресного пространства задач
Для того чтобы запретить пользовательским задачам модифицировать области памяти, принадлежащие самой ОС, необходимо иметь специальные средства. Од- ного разграничения адресных пространств через механизм сегментов мало, ибо можно указывать различные значения адреса начала сегмента и тем самым полу- чать доступ к чужим сегментам. Другими словами, необходимо в явном виде раз- граничивать системные сегменты данных и кода от сегментов, принадлежащих пользовательским программам. Поэтому были введены два основных режима рабо- ты процессора: пользователя и супервизора. Большинство современных процессо- ров имеют по крайней мере два этих режима. Так, в режиме супервизора програм- ма может выполнять все действия и иметь доступ по любым адресам, тогда как в
пользовательском режиме должны быть ограничения, с тем, чтобы обнаруживать и пресекать запрещенные действия, перехватывая их и передавая управление су- первизору ОС. Часто в пользовательском режиме запрещается выполнение команд ввода/вывода и некоторых других, чтобы гарантировать, что только ОС выполняет эти операции. Можно сказать, что эти два режима имеют разные уровни привиле- гий.
В микропроцессорах i80x86 имеются не два, а четыре уровня привилегий. Час- то уровни привилегий называют кольцами защиты, поскольку это иногда помогает объяснить принцип действия самого механизма; поэтому говорят, что некоторый программный модуль «исполняется в кольце защиты с таким-то номером». Для указания уровня привилегий используются два бита, поэтому код 00 обозначает самый высший уровень, а код 11
(2)
(=3) – самый низший. Самый высокий уровень привилегий предназначен для операционной системы (прежде всего, для ядра ОС),
138
самый низкий – для прикладных задач пользователя. Промежуточные уровни при- вилегий введены для большей свободы системных программистов в организации надёжных вычислений при создании ОС и иного системного ПО. Предполагалось,
что уровень с номером (кодом) 1 может быть использован, например, для систем- ного сервиса – программ обслуживания аппаратуры, драйверов, работающих с пор- тами ввода/вывода. Уровень привилегий с кодом 2 может быть использован для создания пользовательских интерфейсов, систем управления базами данных и т. п.,
то есть для реализации специальных системных функций, которые по отношению к супервизору ОС ведут себя как обычные приложения. Так, например, система OS/2
использует три уровня привилегий: с нулевым уровнем привилегий исполняется код самой ОС, на втором уровне исполняются системные процедуры подсистемы ввода/вывода, на третьем уровне исполняются прикладные задачи пользователей.
Однако чаще всего на практике используются только два уровня – нулевой и тре- тий. Таким образом, упомянутый режим супервизора для микропроцессоров i80x86
соответствует выполнению кода с уровнем привилегий 0 (его обозначают так:
PL0 1
). Подводя итог, можно констатировать, что именно уровень привилегий задач определяет, какие команды в них можно использовать и какое подмножество сег- ментов и/или страниц в их адресном пространстве они могут обрабатывать.
Основными системными объектами, которыми манипулирует процессор при работе в защищённом режиме, являются дескрипторы. Дескрипторы сегментов со- держат информацию об уровне привилегий соответствующего сегмента кода или данных. Уровень привилегии исполняющейся задачи определяется значением поля привилегий, находящегося в дескрипторе её текущего кодового сегмента. Напом- ним, что в каждом дескрипторе сегмента (см. рис.3.3) имеется поле DPL в байте прав доступа, которое и определяет уровень привилегии связанного с ним сегмен- та. Таким образом, поле DPL текущего сегмента кода становится полем CPL. При обращении к какому-нибудь сегменту в соответствующем селекторе указывается запрашиваемый уровень привилегий RPL
2
(см. рис. 3.4).
1
PL (privilege level) – уровень привилегий.
2
RPL (requested privilege level) – запрашиваемый уровень привилегий. Поле RPL определяется программистом (сис- темой программирования). В отличие от поля DPL поле RPL легко может быть изменено.