Windows 3.x как расширение MS-DOS



При обсуждении управления памятью в Windows 3.х следует вспомнить, что Windows являлась всего-навсего расширением DOS с графическим интерфейсом. Windows состоит из двух главных составных частей: расширителя DOS и операционной среды. Windows загружается над DOS и во многом на нее “полагается”, поэтому структуры Windows во многом определены DOS. Однако при этом Windows обеспечивает большое количество средств обслуживания, традиционно предоставляемых операционными системами (управление памятью и задачами, динамическое связывание и т.д.).

При создании Windows 3.0 Microsoft и другие компании разработали интерфейс, который позволил бы Windows сосуществовать с другими расширителями DOS. Это соглашение привело к спецификации DPMI (DOS Protected Mode Interface) для DOS, которая определяет общие принципы, на которых должны строиться расширители DOS. Драйвер устройства или программа, обеспечивающая услуги DPMI, называется DPMI-сервером. Windows, выполняющаяся в защищенном режиме, является клиентом DPMI.

Windows использует два различных DPMI-сервера. Файл DOSX.EXE является довольно простым DPMI-сервером, работающем на 286-х процессорах и выше, он обеспечивает сокращенный вариант DPMI и не поддерживает виртуальную память. Другой DPMI-сервер находится внутри менеджера виртуальной машины (Virtual Machine Manager) в WIN386.EXE. Он представляет реализацию полного 32-битного DPMI и поддерживает виртуальную память, используя замещение страниц.

DPMI определяет набор услуг, которые могут использовать расширители для совместной работы (управление оперативной память, обработка прерываний, переключения из реального режима в защищенный и обратно). Опираясь на эти услуги, “над ними” выполняются программы KRNL286.EXE и KRNL386.EXE, являющиеся версиями Windows KERNEL - “ядра” системы. Эти программы выборочно обрабатывают исключения и прерывания, на которые модуль KERNEL должен реагировать не так, как это делают обработчики DOSX/WIN386. KERNEL начинает выполняться в реальном режиме, как обычная программа DOS, затем она, выполнив минимальную настройку, переключается в защищенный режим.

При этом управление памятью, осуществляемое WIN386 и DOSX, и функционирование менеджера памяти модуля KERNEL - совершенно разные процессы, первый процесс вообще никак не зависит от второго. Сам KERNEL не манипулирует глобальной таблицей дескрипторов и не выполняет замещение страниц памяти, эти проблемы полностью лежат на DOSX или WIN386, а KERNEL использует интерфейс DPMI для передачи им указаний о том, что нужно делать. Для связи используется прерывание 31h. KERNEL управляет памятью, оперируя сегментами и блоками памяти, размещенными с помощью DPMI. WIN386 организует виртуальную память, создавая широкий диапазон линейных адресов, которым может соответствовать или не соответствовать физическая память. Линейный адрес, с которым оперирует KERNEL, не обязательно соответствует физическому адресу. KERNEL, в свою очередь, размещает большие блоки линейной памяти, полученные от DOSX или WIN386 через DPMI, и управляет ими, используя стандартные алгоритмы организации “кучи”. Тот факт, что часть памяти, размещенной WIN386, может физически не существовать, не важен для KERNEL. Windows на уровне управления памятью модулем KERNEL в действительности не заботится о механизме замещения страниц и виртуальной памяти.

Используя DPMI-уровень управления памятью, KERNEL размещает большие области памяти, размер которых составляет обычно 64 Кб или 128 Кб, и управляет глобальной кучей, что приводит к дроблению этих областей на меньшие участки, доступные через селекторы. Блоки глобальной кучи делятся на участки, используемые под локальную кучу.

Специфика архитектуры процессоров такова, что KERNEL должен обеспечить два вида управления памятью.

Для каждого блока глобальной кучи, вырезанного из большого DPMI-блока, существует связанный с ним селектор. Программе, разместившей всю свою память в глобальной куче, пришлось бы при каждом запросе на память использовать новый селектор, а их количество ограничено. Чтобы решить эту проблему, программа может оперировать маленькими блоками памяти, расположенными внутри блока глобальной кучи, не распределяя для этого новый селектор. Управление этими блоками называют локальной кучей. KERNEL предоставляет для работы с локальной кучей полный набор функций.

Блоку глобальной кучи эквивалентен блок памяти, выделяемый в DOS функцией 48h INT21h. Эквивалента блоку локальной кучи в DOS нет, но библиотеки многих систем программирования предоставляют программистам функции, которые создают и управляют кучами в пределах блока, выделенного DOS.

Главная причина использования двух типов куч состоит в том. что накладные расходы, связанные с размещением системных блоков памяти, намного больше расходов на поддержку “дополнительной кучи” внутри основной. Размещение блоков в локальной куче Windows не приводит к выделению нового селектора, а обслуживание каждого такого блока требует гораздо меньше кода, чем работа с блоками в глобальной куче.

Управление глобальной кучей составляет основу кода управления памятью в Windows. Код управления глобальной кучей манипулирует памятью в терминах 16-битных логических номеров (handle). Каждый блок памяти, размещенный в глобальной куче, имеет связанный с ним селектор. Все селекторы индексируют локальную таблицу дескрипторов. Между значением логического номера блока и значением селектора есть математическая зависимость. Но Windows 3.0 выполняет код приложений на первом кольце защиты, а в Windows 3.1 - на третьем уровне привилегий. Поэтому единообразия при определении зависимости в разных версиях нет.

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

Менеджер глобальной кучи сохраняет информацию о принадлежности выделенного блока памяти. Когда задача использует объекты памяти, PDP задачи, которая разместила объекты памяти, владеет этой памятью (PDP в точности соответствует PSP в DOS). Завершение задачи приводит к освобождению всех сегментов, которыми владеет эта задача.

При этом возникает проблема, связанная с использованием DLL: память, размещенная внутри DLL, принадлежит PDP текущей задачи, т.е. задаче, которая сделала вызов функции из DLL. Когда задача завершается, KERNEL просматривает глобальную кучу и освобождает любые блоки памяти, которые данная задача “забыла” освободить. Если в работу включается другая задача, которая использует этот же модуль DLL, размещенный им блок оказывается больше недоступным, и попытка доступа к нему приводит к ошибке. Для соблюдения правильной принадлежности блоков памяти следует использовать атрибуты: блоки, размещенные с атрибутом GMEM_SHARE/GMEM_DDESHARE, принадлежат запрашивающему их модулю (т.е. модулю, которому принадлежит сегмент кода, выполнивший запрос на память), если же память размещена без этого атрибута, она будет принадлежать задаче, которая является активной на момент размещения.

Глобальная куча содержит также объекты, используемые KERNEL для управления самой кучей.

Локальная куча похожа на глобальную, но при выделении памяти в ней возвращается ближний 16-битный указатель (смещение). Код управления локальной кучей манипулирует блоками памяти в терминах их логических номеров. В локальной куче можно размещать FIXED-блоки (при их выделении получается непосредственный адрес, который можно использовать без каких-либо преобразований), но такая возможность таит опасность фрагментации. Логический номер размещаемого в локальной куче MOVEABLE-блока памяти - это смещение в структуре данных, которая расположена внутри локальной кучи. В этой структуре хранится фактический адрес блока памяти, а также его счетчик блокировок и флаги. Поэтому для получения содержимого самого блока выполняется двойная переадресация. Проще блокировать такие блоки при необходимости, как и в глобальной куче, и работать с указателями, и разблокировать, когда это нужно.

Адресное пространство программы - это память, которую она может “видеть”. В MS-DOS в реальном режиме одно и то же адресное пространство используется всеми программами от ОС до программ пользователей. В других ОС (OS/2, Windows 95, Windows NT) обеспечивается отдельное адресное пространство для каждого процесса. Windows 3.1 находится “между” этими крайностями. Все Windows-программы выполняются на одной виртуальной машине и разделяют одно и то же адресное пространство, для всех задач используется одна и та же LDT. Общее адресное пространство позволяет легко реализовать взаимодействие между программами, для этого достаточно передать от одного приложения другому дальний указатель на передаваемые данные. Но это ослабляет систему защиты. Каждый сеанс DOS является отдельной виртуальной машиной.

Поддержка виртуальной памяти реализована в виде размещаемых на жестком диске файлов подкачки (swap files). Эти файлы позволили увеличить объем памяти, которым могло пользоваться приложение: приложение считает доступным суммарный объем памяти (емкость оперативной памяти плюс размер файла подкачки).

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


Дата добавления: 2016-01-05; просмотров: 36; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!