Файл: Учебнометодическое пособие Томск 2016 2 удк 004. 451(075. 8) Ббк 32. 973. 2018. 2я73 к 754 Рецензенты.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 07.11.2023
Просмотров: 346
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
159 старшего бита в регистре CR0), то в качестве линейной памяти, используемой для размещения сегментов процесса, выступает реальная ОП. В этом случае любой адрес
,
,
,
S L
T I L
, содержащийся в поле машинной команды, преоб- разуется при попадании этой команды на ЦП в реальный адрес ОП по схеме, изображенной на рисунке 6.3:
R B L
, где B – базовый адрес сегмента, дескриптор которого находится или в таблице
GDT(если
T 0
) или в таблице LDT (если
T 1
) со смещением I байт относи- тельно начала таблицы.
Рис. 6.3 Преобразование виртуального сегментного адреса в реальный при отсутствии аппаратуры управления страницами.
T
– тип таблицы дескрипторов (0 – GDT,1 – LDT),
I – индекс дескриптора сегмента в GDTили LDT,
L – смещение относительно начала сегмента,
B – базовый линейный адрес сегмента,
R – реальный адрес первой ячейки сегмента
Теперь дополним изложенную выше схему адресации ячеек ОП в защи- щенном режиме некоторыми существенными деталями: рассмотрим достаточно подробно структуру дескрипторов сегментов, а также используемые для работы с этими дескрипторами регистры и машинные команды. Начнем с вопроса о том, где размещается сегментный виртуальный адрес ячейки ОП – (S,L).
160
Напомним, что в процессоре i8086 идентификатор сегмента S есть номер начального параграфа сегмента. При этом S содержится в том сегментном ре- гистре, который используется для адресации рассматриваемой ячейки ОП.
Каждая машинная команда «знает», какой сегментный регистр используется для адресации операнда этой команды, если этим операндом является ячейка
ОП. Например, команда безусловного перехода jmp выполняет переход на ячейку памяти, для адресации которой используется регистр сегмента кода CS.
Это справедливо и для адресации ячеек ОП в реальном режиме процессора i80386. В защищенном режиме ЦП для хранения S также используется один из сегментных регистров. Но так как теперь
,
S
T I
, то и содержимое сегментно- го регистра в защищенном режиме будет другим (рис. 6.4). Поле RPL использу- ется для аппаратной защиты информации в ОП и будет рассмотрено нами в пп. 6.2.3.
Рис. 6.4 Структура сегментного регистра в защищенном режиме.
I
– индекс дескриптора сегмента в таблице GDT или LDT,
T
– тип таблицы дескрипторов (0 – GDT, 1– LDT),
RPL
– уровень запрашиваемых привилегий
Обратим внимание, что размер поля индексов I в сегментном регистре составляет 13 бит. Поэтому максимальная длина (в байтах) GDT или LDT равна
2 13
= 8 192. Так как длина одного дескриптора равна 8 байтам, то максимальное число дескрипторов в таблице GDT или LDTбудет: 8 192/8 = 1 024 = 1 K. Такое максимальное число сегментов памяти может иметь конкретная прикладная программа или ядро ОС.
На рисунке 6.5 приведена структура дескриптора сегмента (строка GDT или LDT). Его длина 8 байт, из которых базовый линейный адрес сегмента (B) занимает 4 байта, или 32 бита. Так как 2 32
= 4 Г, то общий объем линейного виртуального адресного пространства составляет 4 Гбайт.
161
Рис. 6.5 Структура дескриптора сегмента
Поле предел содержит размер сегмента в байтах, уменьшенный на 1.
В реальном режиме размер сегмента ОП составляет 64 K. В защищенном режи- ме можно задавать любую длину сегмента от 1 байта до 2 20
= 1 M байтов или страниц. Бит G – бит гранулярности. Если
G 1
, то поле предела задает пре- дельный размер сегмента в страницах (по 4 096 байтов), иначе – в байтах.
Бит X задает размерность машинных команд, выполняемых ЦП. Если
X 1
, то выполняются 32-битные команды, иначе – 16-битные. (16-битные ко- манды остались «в наследство» от процессора i8086). Бит l используется опе- рационной системой для своих нужд.
Поле (байт) доступ ограничивает операции, которые можно выполнять над сегментом. При этом бит S– признак системного сегмента. Если этот бит сброшен в 0, то сегмент системный. Поле DPL используется для организации защиты сегмента. Его назначение будет рассмотрено в пп. 6.2.3. Биты P и A ис- пользуются для организации сегментного свопинга. Эти биты будут рассмотре- ны в пп. 6.2.2. Содержание поля тип определяется назначением сегмента. На рисунке 6.6 приведен байт доступа для сегмента кода, содержащего машинные команды программы. Здесь бит C – бит подчинения. R – бит разрешения чте- ния сегмента (1 – чтение разрешено, 0 – чтение запрещено). Что касается за- писи, то в сегмент кода она запрещена всегда (в отличие от реального режима).
Рис. 6.6 Байт доступа для сегмента кода
На рисунке 6.7 приведен байт доступа для сегмента данных. Здесь бит D задает направление расширения сегмента. Обычный сегмент данных расширя-
162 ется в направлении старших адресов (
D 0
). Если же в сегменте расположен стек, расширение происходит в обратном направлении (
D 1). W – бит разреше- ния записи в сегмент (1 – запись допустима, 0 – нет). Если программа попыта- ется записать в сегмент при
W 0
, то ее выполнение будет прервано. Для си- стемных сегментов поле «тип» принимает другие значения.
Рис. 6.7 Байт доступа для сегмента данных
Так как GDT содержит дескрипторы сегментов ядра ОС, эта таблица за- полняется при инициализации ОС. Что касается LDT, то она содержит дескрип- торы сегментов только одного процесса и ее создание инициируется процес- сом-отцом при выполнении системного вызоваСОЗДАТЬ_ПРОЦЕСС. Если предположить, что мы занимаемся созданием нового процесса самостоятельно, не используя данный системный вызов, то для задания LDT дочернего процесса наша программа могла бы использовать, например, следующие операторы ас- семблера:
; Первая строка любой GDT или LDT содержит нули
Ldt db 0,0,0,0,0,0,0,0
; Дескриптор сегмента кода (выполнение, чтение, 32- битные команды) db 0FFh, 0FFh, 0, 0, 0, 0FAh, 4Fh, 0
; Дескриптор сегмента данных (рост вверх, чтение, за- пись) db 0FFh, 0FFh, 0, 0, 0, 0F2h, 4Fh, 0
При рассмотрении данного примера следует учесть, что в операторе db младший байт дескриптора расположен слева, а на рисунке 6.1, наоборот, спра- ва. В качестве базового линейного адреса для обоих сегментов выбран нулевой адрес. Что касается предельной длины сегментов, то она тоже одинакова
(1 Мбайт). Следовательно, оба дескриптора описывают один и тот же сегмент линейной памяти. В первом случае этот сегмент рассматривается как сегмент кода, а во втором – как сегмент данных. В результате процесс имеет по отно- шению к своей собственной памяти неограниченные права доступа.
Анализ данного примера позволяет сделать еще один вывод. Так как ба- зовый линейный адрес сегмента нулевой, то в данном примере речь может идти
163 только о виртуальном линейном пространстве, для отображения которого на реальные адреса требуется аппаратура управления страницами. (В самом нача- ле реальной ОП находится таблица векторов прерываний, используемая ЦП в реальном режиме работы.)
Область памяти, в которой находится LDT будущего процесса, должна быть зарегистрирована процессом-отцом в таблице GDT как особый системный сегмент памяти. Для того чтобы выполнить запись соответствующего дескрип- тора в таблицу GDT, эту таблицу необходимо найти в памяти. Это можно сде- лать, прочитав содержимое регистра GDTR. Этот 6-байтовый регистр содержит
4-байтовый базовый реальный адрес таблицы GDT и 2-байтовый размер этой таблицы.
GDTR– очень важный регистр, используемый самим ЦП для адресации ячеек памяти. Допустим, например, что в сегментном регистре кода CS бит
T 0
. Тогда для определения адреса следующей выполняемой команды ЦП просуммирует содержимое GDTR с содержимым поля индекса в регистре CS, а затем извлечет из найденного дескриптора базовый линейный адрес сегмента кода, который и будет просуммирован со смещением из регистра EIP.
Для заполнения регистра GDTR программы ядра ОС используют специ- альную машинную команду lgdt. Она выполняется, например, после добавле- ния в GDT нового дескриптора LDT.
Если в сегментном регистре бит
T 1
, то дескриптор искомого сегмента находится в LDT. Так как в любой момент времени на ЦП выполняется только один программный процесс, то только одна таблица LDT должна быть «види- ма» процессором. Для этого ЦП имеет 2-байтовый регистр
1 ... 11 12 13 14 15 16 17 18 ... 23
LDTR. Этот регистр содержит индекс дескриптора текущей таблицы LDT в таблице GDT.
Специальная машинная командаlldt выполняет замену содержимого регистра LDTR. Записав с ее помощью в LDTR индекс дескриптора LDT в GDT, мы сделаем данную LDT текущей. Теперь любой сегментный регистр с битом
T 1 будет указывать на один из сегментов, определенных (с помощью своих дескрипторов) именно в этой таблице. При этом следует отметить, что кроме
LDTR в ЦП имеется внутренний программно недоступный регистр, содержа- щий базовый линейный адрес текущей LDT, а также ее размер. Запись в него
ЦП осуществляет при выполнении командыlldt путем копирования полей адреса и размера из дескриптора LDT в таблице GDT. Наличие такого внутрен-
164 него регистра позволяет ЦП достаточно быстро вычислять линейные адреса ячеек в сегментах, определенных в текущей LDT.
6.2.2 Распределение памяти
В отличие от процессора i8086 наличие аппаратуры управления сегмен- тами в процессорах, начиная с i80386, обусловлено не стремлением расширить объем адресуемой памяти, а следующими причинами. Во-первых, благодаря дескрипторам сегментов, решается задача аппаратной защиты информации в
ОП. При этом возводится достаточно надежный «забор» между сегментами па- мяти разных процессов. Методы реализации такой защиты будут рассмотрены в пп. 6.2.3.
Во-вторых, сегментная организация памяти существенно упрощает ис- пользование одной и той же области памяти несколькими процессами. В каче- стве таких областей могут рассматриваться реентерабельные программы, DLL, а также разделяемые области данных. Например, неизменяемый код реентера- бельной программы выделяется в каждом из процессов в отдельный сегмент кода. (На аппаратном уровне для сегмента кода обеспечивается запрет какой- либо записи.) При создании первого процесса, использующего данную реенте- рабельную программу, производится загрузка этой программы в память
(ОП + область свопинга), а в LDT процесса помещается дескриптор сегмента кода, содержащий виртуальный линейный адрес загруженной программы. При создании всех последующих процессов в ихLDT также помещаются дескрип- торы сегментов кода, содержащие виртуальные линейные адреса реентерабель- ного сегмента. При отсутствии аппаратуры управления страницами эти линей- ные адреса будут совпадать, а при наличии такой аппаратуры виртуальные линейные адреса реентерабельного сегмента кода будут, скорее всего, разными.
Так как сегменты данных у каждого из процессов свои, то никакого влияния процессов друг на друга нет.
Реентерабельный код DLL также записывается в отдельный сегмент кода, который может использовать любой процесс. Для этого требуется поместить дескриптор сегмента в LDT процесса. Очевидно, что каждый процесс должен иметь свой экземпляр сегмента данных DLL, а его дескриптор – в своей LDT.
Использование для информационного взаимодействия между процессами раз- деляемого сегмента данных предполагает размещение в LDT каждого процесса
165 своего дескриптора этого сегмента. Подобное размещение выполняет ядро при выполнении системного вызоваСОЗДАТЬ_РАЗДЕЛЯЕМЫЙ_СЕГМЕНТ.
Перечисленные достоинства сегментной организации памяти уменьшают потребности процессов в ОП, но не устраняют такую потребность совсем. Рас- смотрим распределение ОП при наличии аппаратуры управления сегментами и отсутствии аппаратуры управления страницами. Решение этой задачи воз- можно двумя способами.
Простейший подход предполагает, что суммарный объем сегментной виртуальной памяти всех процессов не может превышать объем ОП. В этом случае для выделения памяти новому процессу ОС рассматривает свободные участки памяти, оставшиеся после первоначальной загрузки в ОП ядра ОС, а также программ предыдущих процессов. Например, допустим, что перед со- зданием процесса 4 ОП имеет состояние, изображенное на рисунке 6.8.
Рис. 6.8 Пример распределения памяти
Если общая длина программы процесса 4 превышает 4,5 Мбайт, то в дан- ный момент требуемая память выделена быть не может и создание процесса от- кладывается до ее появления. Если длина программы не превышает суммарного объема свободной ОП, то возможны два варианта. Во-первых, программа мо- жет быть легко загружена в память, если для каждого сегмента программы име- ется не меньший свободный участок ОП. Если это не так, то ОС должна «сдви- нуть» в памяти ранее загруженные программы процессов. Например, пусть процесс 4 имеет 2 сегмента длиной по 2 Мбайта. Тогда без перемещения про-
166 граммы 2 в сторону больших или меньших адресов программа процесса 4 за- гружена быть не может.
Изложенная простейшая схема распределения ОП исходит из предполо- жения, что суммарный объем виртуальной памяти процессов не превышает суммарного объема реальной ОП. (При этом разделяемые сегменты кода или данных учитываются лишь один раз.) Но аппаратура управления сегментами в i80386 позволяет отойти от этого предположения и загружать в память мень- шего объема большую по размеру программу. Иными словами, виртуальная сегментная память процесса может быть больше, чем выделенная процессу ре- альная ОП.
Реализация подобного подхода основана на наличии в дескрипторе каж- дого сегмента битов P (бит присутствия) и A (бит обращения к сегменту), а также на наличии у процессора исключения отказ сегмента. Совместная ра- бота аппаратуры и ядра ОС заключается в следующем.
Когда на ЦП попадает адрес ячейки в виде
,
,
T I L
, то аппаратно прове- ряется бит P в искомом дескрипторе. Если
P 1 (сегмент в ОП), то выполнение программы продолжается, иначе – возникает исключение отказ сегмента. Его обработчик подкачивает требуемый сегмент из ВП. Так как для размещения этого сегмента может потребоваться откачка другого сегмента, то для опреде- ления откачиваемого сегмента может помочь бит A. Если он сброшен, то к сег- менту не было обращения, и он может быть откачан.
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
Перекачка сегментов между ОП и ВП называется сегмент-
ным свопингом.
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
Распределение ОП, основанное на свопинге, обладает тем существенным недостатком: вследствие неодинаковой длины сегментов размещение одного сегмента может потребовать откачку и (или) перемещение в ОП не одного, а нескольких других сегментов [8].
6.2.3 Защита информации в оперативной памяти
Защита информации является необходимым условием функционирования мультипрограммной системы. В любой ВС информация находится в ОП и на
ПУ. Так как оперативная память распределяется между процессами в виде сег- ментов, то требуется исключить воздействие процессов на сегменты памяти, не