Создание VxD на Visual C++ без ассемблерных модулей
Страница 6. Доступ к памяти


 

Доступ к памяти

В контексте приложения Win32 или виртуальной машины DOS драйвер имеет прямой доступ к их адресному пространству. Для виртуальных машин требуется лишь приведение 16-разрядных адресов типа «сегмент:смещение» к линейным, расположенным в пределах первого мегабайта 32-разрядного адресного пространства.

В контексте 16-разрядного приложения Windows подобной «прямой видимости» нет, и для прямого доступа к данным приложения необходимо выполнить отображение (mapping) фрагментов 16-разрядного адресного пространства приложения в «плоское» (flat) 32-разрядное адресное пространство драйвера. В результате этой операции в области системных адресов создаются страницы, отображенные на те же адреса физической памяти, что и заданные адреса 16-разрядного приложения.

После завершения работы с данными отображение необходимо прекратить (unmap), чтобы освободить созданные в системной области страницы.

Поскольку системная область (system arena) доступна для чтения всем приложениям Win32, они могут считывать локальные данные VxD по возвращенным им указателям. Однако доступ приложений к системой области памяти в общем случае не рекомендуется.

Повторная входимость

VMM в общем случае не является повторно-входимым (реентерабельным) модулем. Функции VMM делятся на асинхронные, которые могут быть вызваны в любой момент (даже внутри обработчика прерывания), и обычные, которые могут вызваны лишь внутри «вертикального» потока управления, когда управление передается строго сверху вниз, без рекурсий.

Большинство функций VxD, вызываемых извне, не требует обеспечения повторной входимости. Однако вызовы функций, происходящие в результате асинхронных событий (обычно это прерывания), могут накладываться, если обработка предыдущего вызова не успела завершиться или реализована некорректно. Поэтому при проектировании VxD, имеющих дело с асинхронными событиями, этому вопросу необходимо уделять особое внимание.

Загрузка, работа и выгрузка драйвера

Все VxD загружаются в системную область памяти (system memory arena), начинающуюся с адреса 0xC0000000. Сразу после загрузки статическому драйверу — сообщение DEVICE_INIT; динамическому драйверу передается сообщение SYS_DYNAMIC_DEVICE_INIT.

Последовательность передачи сообщений при инициализации статического драйвера на самом деле немного сложнее; точное описание процесса можно найти в документации DDK.

Фаза инициализации драйвера обычно состоит в установке начальных значений переменных, запросе рабочих областей памяти, настройке режимов работы устройств, назначении векторов прерываний, каналов DMA и т.п.

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

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

Ответственность за корректную «чистку» перед выгрузкой динамического драйвера возложена на его разработчика. Система не в состоянии проверить, действительно ли удалены все ссылки на объекты драйвера; если, например, драйвер сделал запрос на таймерное или иное событие, после чего был выгружен и не аннулировал этого запроса — при наступлении события VMM попытается вызвать заданную процедуру обработки, которая к этому времени уже не существует, что приведет к непредсказуемым последствиям, вплоть до полного зависания системы.

 
« Предыдущая статья   Следующая статья »