Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование для Windows NT

© Александр Фролов, Григорий Фролов
Том 26, часть 1, М.: Диалог-МИФИ, 1996, 272 стр.

[Назад] [Содеожание] [Дальше]

Немного истории

Для того чтобы вам было легче разобраться с системой управления памятью Microsoft Windows NT и ощутить, насколько она совершенна, сделаем краткий обзор принципов управления памятью, положенных в основу операционных систем MS-DOS и Microsoft Windows версии 3.1.

Управление памятью в MS-DOS

Принципы управления памятью в операционной системе MS-DOS и соответствующий программный интерфейс были рассмотрены нами в 19 томе “Библиотеки системного программиста”, который называется “MS-DOS для программиста”.

Напомним, что MS-DOS использует так называемый реальный режим работы процессора XE "реальный режим работы процессора" . Такие операционные системы, как Microsoft Windows версии 3.1, Microsoft Windows 95, Microsoft Windows NT и IBM OS/2 на этапе своей загрузки переводят процессор в защищенный режим работы. Подробно эти режимы мы описали в 6 томе “Библиотеки системного программиста”, который называется “Защищенный режим работы процессоров 80286/80386/80486”.

В реальном режиме работы процессора физический адрес XE "физический адрес" , попадающий на шину адреса системной платы компьютера составляется из двух 16-разрядных компонент, которые называются сегментом XE "сегмент" и смещением XE "смещение" (рис. 1.1).

Рис.1.1. Получение физического адреса в реальном режиме работы процессора

Процедура получения физического адреса из сегмента и смещения очень проста и выполняется аппаратурой процессора. Значение сегментной компоненты сдвигается влево на 4 бита и дополняется справа четырьмя нулевыми битами. Компонента смещения расширяется до 20 разрядов записью нулей в четыре старших разряда. Затем полученные числа складываются, в результате чего образуется 20-разрядный физический адрес.

Задавая произвольные значения для сегмента и смещения, программа может сконструировать физический адрес для обращения к памяти размером чуть больше одного мегабайта. Точное значение с учетом наличия области старшей памяти XE "область старшей памяти" High Memory Area XE "High Memory Area" равно 1 Мбайт + 64 Кбайт - 16 байт.

Хорошо знакомая вам из программирования для MS-DOS комбинация компонет [сегмент : смещение] называется логическим адресом XE "логический адрес" реального режима. В общем виде процедура преобразования логического адреса в физический схематически изображена на рис. 1.2.

Рис. 1.2. Преобразование логического адреса в физический

Программы никогда не указывают физические адреса памяти, а всегда работают только с логическими адресами. Это верно как в реальном режиме работы процессора, так и в защищенном. Так как перобразователь адреса реализован аппаратно в процессоре, процесс преобразования не замедляет работу программы.

Логические адреса реального режима находятся в диапазоне от [0000h : 0000h] до [FFFFh : 000Fh]. Это соответствует диапазону физических адресов от 00000h до FFFFFh, лежащих в пределах первого мегабайта оперативной памяти. Задавая логические адреса в пределах от [FFFFh : 0010h] до [FFFFh : FFFFh], можно адресовать область старшей памяти High Memory Area, имеющей размер 64 Кбайт - 16 байт.

Таким образом, схема преобразования адреса реального режима не позволяет адресовать больше одного мегабайта памяти, что явно недостаточно для работы современных приложений. Даже если в вашем компьютере установлено 16 Мбайт памяти, операционная система MS-DOS не сможет адресовать непосредственно старшие 15 Мбайт (рис. 1.3).

Рис. 1.3. Адресация памяти в MS-DOS

Несмотря на то что, как мы только что сказали, программы используют не физические, а логические адреса, преобразователь адреса реального режима позволяет программам легко сконструировать логический адрес для любого нужного ей физического адреса. В этом смысле можно говорить о возможности физической адресации памяти в реальном режиме.

Такая возможность сильно снижает надежность операционной системы MS-DOS, так как любая программа может записать данные в любую область памяти. В том числе, например, в область памяти, принадлежащей операционной системе или в векторную таблицу прерываний. Неудивительно, что компьютер, работающий под управлением MS-DOS, часто зависает, особенно при использовании плохо отлаженных программ.

Что же касается программного интерфейса для управления памятью в MS-DOS, то такой существует в рамках прерывания INT 21h XE "INT 21h" . Он позволяет программам заказывать и освобождать области памяти, лежащие в границах первого мегабайта. Однако ничто не мешает программам выйти за пределы полученной области памяти, выполнив при этом самоликвидацию или уничтожение операционной системы.

Управление памятью в Microsoft Windows версии 3.1

Подробно схема управления памятью в Microsoft Windows версии 3.1 и соответствующие функции программного интерфейса мы описали в 13 томе “Библиотеки системного программиста”, который называется “Операционная система Microsoft Windows 3.1 для программиста. Часть третья”. Здесь же мы остановимся только на самых важных моментах, необходимых для понимания отличий этой схемы от схемы адресации памяти в Microsoft Windows NT.

Адресация памяти

Приложения, запущенные в среде Microsoft Windows версии 3.1, работают с логическими адресами защищенного режима. Логический адрес защищенного режима, так же как и реального режима, состоит из двух компонент. Однако для защищенного режима это не сегмент и смещение, а селектор и смещение.

В стандартном режиме Microsoft Windows селектор и смещение всегда являются 16-разрядными. Когда Microsoft Windows работает в расширенном режиме, одна из компонент этой операционной системы (виртуальные драйверы VxD) работает в режиме 32-разрядной адресации. При этом селектор XE "селектор" является 16-разрядным, а смещение XE "смещение" - 32-разрядным. Что же касается обычных приложений, то и в расширенном режиме они не используют все возможности процессора 80386. В частности, размеры сегментов обычного приложения Windows не превышают 64 Кбайт.

Тем не менее расширенный режим работы обладает большим преимуществом: в нем используется страничная адресация и виртуальная память. Схема адресации для стандартного режима была описана в 13 томе “Библиотеки системного программиста”. Виртуальные драйверы описаны в 17 томе этой же серии книг.

В 32-разрядном режиме адресации (который в Microsoft Windows версии 3.1 используется только виртуальными драйверами) выполняется двухступенчатое преобразование логического адреса в физический, показанное на рис. 1.4.

Рис. 1.4. Преобразование логического адреса в физический для 32-разрядного режима

На первом этапе логический адрес, состоящий из 16-разрядного селектора и 32-разрядного смещения, преобразуется в 32-разрядный линейный адрес XE "линейный адрес" .

Если бы линейный адрес отображался один к одному на физический (что возможно), то с его помощью можно было бы адресовать 232 = 4294967296 байт памяти, то есть 4 Гбайт. Дальнейшие преобразования линейного адреса в 32-разрядный физический адрес с использованием механизма страничной адресации позволяют еще больше расширить размер адресуемой памяти. И хотя в Microsoft Windows версии 3.1 приложения не могут использовать больше 256 Мбайт виртуальной памяти, операционная система Microsoft Windows NT успешно преодалевает этой барьер. Забегая вперед, скажем, что каждому приложению Microsoft Windows NT доступно ни много ни мало как… 2 Гбайта виртуальной памяти! Лишь бы в компьютере были установлены диски подходящей емкости.

Как же выполняется преобразование логического адреса в линейный в защищенном режиме работы процессора?

Как мы говорили в 6 и 13 томах “Библиотеки системного программиста”, для данного преобразования используется одна глобальная таблица дескрипторов GDT XE "GDT "(Global Descriptor TableXE "Global Descriptor Table") и несколько локальных таблиц дескрипторов LDT XE "LDT "(Local Descroptor TableXE "Local Descroptor Table"). Это справедливо как для Microsoft Windows версии 3.1, так и для Microsoft Windows NT.

В таблицах дескрипторов хранятся элементы, описывающие отдельные сегменты памяти. В этих элементах среди всего прочего хранится одна из компонент линейного адреса - так называемый базовый адрес XE "базовый адрес" , имеющий 32 разряда. Преобразователь логического адреса в линейный складывает базовый адрес и 32-разрядное смещение, в результате чего получается 32-разрядный линейный адрес.

Селектор предназначен для индексации внутри одной из перечисленных выше таблиц дескрипторов. Селектор состоит из трех полей - индекса, индикатора TI и поля уровня привилегий RPL (рис. 1.5).

Рис. 1.5. Формат селектораXE "формат селектора"

Поле TI (Table IndicatorXE "Table Indicator") используется для выбора глобальной или локальной таблицы дескрипторов. В любой момент времени может использоваться одна глобальная таблица дескрипторов и одна локальная таблица дескрипторов. Если бит TI равен 0, для выборки базового адреса используется глобальная таблица дескрипторов GDT XE "GDT" , если 1 - локальная LDT XE "LDT" .

Поле RPL (Requested Privilege LevelXE "Requested Privilege Level") селектора содержит уровень привилегий, запрошенный приложением при обращении к сегменту памяти, который описывается дескриптором. Программа может обращаться только к таким сегментам, которые имеют соответствующий уровень привилегий. Поэтому программа не может, например, воспользоваться глобальной таблицей дескрипторов для получения доступа к описанным в ней системным сегментам, если она не обладает достаточным уровнем привилегий. На этом основана защита системных данных от разрушения (преднамеренного или в результате программной ошибки) со стороны прикладных программ.

Упрощенная схема преобразования логического адреса в линейный показана на рис. 1.6.

Рис. 1.6. Преобразование логического адреса в линейный

Таблицы дескрипторов создаются операционной системой на этапе ее инициализации перед переключением процессора в защищенный режим и впоследствии могут изменяться как самой операционной системой, так и приложениями (явно или неявно).

Помимо базового адреса, дескрипторы содержат и другую информацию, описывающую сегменты памяти. В частности, в них находится размер сегмента, а также уровень доступа, которым должно обладать приложение для доступа к сегменту.

Если приложение попытается адресовать память, лежащую за пределами области, описанной дескриптором, произойдет аппаратное прерывание. Аналогичная реакция будет и на попытки приложения выполнить неразрешенный доступ, например, сделать попытку записи в сегмент, для которого разрешено только чтение, или в программный сегмент, содержащий исполняемый код. Приложение также не может использовать селекторы, для которых нет заполненных дескрипторов.

Таким образом, в защищенном режиме приложение не может делать с адресами все, что ему вздумается, как это было в реальном режиме. Более подробную информацию об этом вы можете получить из 6 тома “Библиотеки системного программиста”.

Зачем нужно использовать дескрипторные таблицы двух типов?

В мультизадачной операционной системе можно использовать одну глобальную таблицу дескрипторов для описания областей памяти, принадлежащей операционной системе и несколько локальных таблиц дескрипторов для каждого процесса. В этом случае при соответствующей настройке базовых адресов можно изолировать адресные пространства операционной системы и отдельных процессов. Если сделать так, что каждый процесс будет пользоваться только своей таблицей дескрипторов, любой процесс сможет адресоваться только к своим сегментам памяти, описанным в соответствующей таблице, и к сегментам памяти, описанным в глобальной таблице дескрипторов. В системе может существовать только одна глобальная таблица дескрипторов.

Заметим, что операционная система Microsoft Windows версии 3.1 создает одну общую глобальную таблицу дескрипторов, одну таблицу локальных дескрипторов для системной виртуальной машины, в рамках которой работают все приложения Windows, и по одной локальной таблице дескрипторов для каждой виртуальной машины DOS. Подробнее об этом вы можете узнать из главы “Драйверы для Windows” 17 тома “Библиотеки системного программиста”, который называется “Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы”.

Примечательно, что все 16-разрядные приложения Windows версии 3.1 работают в одном адресном пространстве, которое представлено одной локальной таблицей дескрипторов. Это служит одной из причин нестабильности Microsoft Windows версии 3.1, так как плохо отлаженное приложение может разрушить области памяти, принадлежащие другим приложениям, или даже самой операционной системе.

Займемся теперь преобразователем линейного адреса в физический. Процесс такого преобразования имеет самое непосредственное отношение к страничной адресации памяти.

Линейный адрес разделяется на три поля:

·       номер таблицы в каталоге таблиц страниц (10 бит);

·       номер страницы в таблице страниц (10 бит);

·       смещение внутри страницы (12 бит)

Вся память при этом делится на страницы XE "страницы памяти" размером 4096 байт, адресуемые с помощью специальных таблиц страниц. В системе существует один каталог таблиц страниц XE "каталог таблиц страниц" и много таблиц страниц. Таблица страниц XE "таблица страниц" содержит 32-разрядные физические адреса страниц памяти.

В процессе преобразования линейного адреса в физический происходит выбор нужного элемента каталога таблиц и таблицы страниц. Далее к базовому физическому адресу страницы прибавляется смещение, взятое из третьего поля линейного адреса и таким образом получается физический адрес (рис. 1.7).

Рис. 1.7. Преобразование линейного адреса в физический

Отметим, что преобразование линейного адреса в физический выполняется аппаратурой процессора с помощью каталога таблиц страниц XE "каталог таблиц страниц "и таблиц страницXE "таблица страниц", подготовленных операционной системой. Приложение Windows никогда не работает с таблицами страниц или каталогом таблиц страниц. Оно пользуется логическими адресами в формате [селектор : смещение].

Основное преимущество системы управления памятью расширенного режима Windows заключается в возможности использования виртуальной памяти.

Виртуальная память XE "виртуальная память" работает на уровне страниц (описанных в каталогах страниц) и совершенно прозрачна для программиста. Операционная система Windows полностью управляет виртуальной памятью. Если приложение пытается обратиться к странице, отсутствующей в памяти и выгруженной на диск, происходит прерывание, после чего страница подгружается с диска. Вслед за этим работа приложения продолжается.

Пользуясь виртуальной памятью, приложение может заказывать для себя блоки памяти огромного размера. При этом возникает иллюзия работы с очень большой оперативной памятью.

Пулы памяти в Microsoft Windows версии 3.1

Напомним, что в Microsoft Windows версии 3.1 существует глобальная область памяти (глобальный пул XE "глобальный пул" Global Heap XE "Global Heap" ), доступная для всех приложений. Кроме того, для каждого приложения выделяется “в личное пользование” локальный пул XE "локальный пул" Local Heap XE "Local Heap" размером 64 Кбайт.

Если одно приложение получает область памяти из глобального пула, оно может передать адрес этой области другому приложению и то сможет им воспользоваться (так как все приложения работают в одном адресном пространстве). В операционной системе Microsoft Windows NT этот прием работать не будет, так как каждое приложение работает в отдельном адресном пространстве с использованием отдельной локальной таблицы дескрипторов.

Для получения памяти из глобального и локального пула в программном интерфейсе Microsoft Windows версии 3.1 были предусмотрены отдельные функции с именами GlobalAlloc XE "GlobalAlloc" и LocalAlloc XE "LocalAlloc" . Выделенную этими функциями область памяти перед использованием было необходимо зафиксировать, вызвав, соответственно, функции GlobalLock XE "GlobalLock" и LocalLock XE "LocalLock" . Для выделяемых областей памяти автоматически создавались дескрипторы в локальной таблице дескрипторов.

При необходимости приложение могло изменять содержимое глобальной или локальной таблицы дескрипторов, для чего в программном интерфейсе Microsoft Windows версии 3.1 были предусмотрены соответствующие функции. Эти функции, описанные нами в 13 томе “Библиотеки системного программиста”, давали обычным приложениям Windows почти ничем не ограниченные права доступа к памяти. Поэтому можно утверждать, что несмотря на использование защищенного режима работы процессора, по надежности Microsoft Windows версии 3.1 недалеко ушла от операционной системы MS-DOS.

[Назад] [Содеожание] [Дальше]