Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

         

Процесс инициализации


Рассмотрим процесс инициализации виртуального драйвера более подробно.

Вначале в память загружается сегмент инициализации реального режима VXD_REAL_INIT. После загрузки система управления виртуальными машинами VMM (Virtual Machine Manager) вызывает процедуру инициализации реального режима. Она выполняет все необходимые действия перед переключением Windows в защищенный режим, например, сбрасывает обслуживаемое драйвером устройство в исходное состояние или блокирует его. На этапе инициализации в реальном режиме можно выполнить проверку файлов инициализации system.ini и win.ini, резервирование физических страниц памяти для использования устройством. Можно также зарезервировать блок памяти, который имеет отношение к устройству и создается для каждой вновь запускаемой виртуальной машины.

Имя процедуры инициализации реального режима не имеет значения, однако эта процедура должна располагаться в самом начале сегмента инициализации реального режима.

Перед вызовом процедуры регистры процессора устанавливаются следующим образом.

Регистр Описание содержимого регистра
CS, DS, ES Адрес сегмента инициализации реального режима
AH Старший номер версии системы управления виртуальными машинамиVMM
AL Младший номер версии системы управления виртуальными машинами VMM
BX Флаги загрузки:Duplicate_Device_ID повторная загрузка драйвера с тем же идентификатором;Duplicate_From_INT2F повторная загрузка драйвера с тем же идентификатором из списка драйверов прерывания INT 2Fh;Loading_From_INT2F драйвер был определен в списке драйверов прерывания INT 2Fh
ECX Дальний адрес в формате <сегмент:смещение> точки входа сервиса инициализации реального режима
EDX Указатель на данные, полученные из прерывания INT 2Fh. Если данные не передаются, регистр содержит нулевое значение
SI Сегментный адрес блока памяти, содержащего среду (environment) операционной системы MS-DOS
SS:SP Адрес стека

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




Возврат из процедуры инициализации реального режима должен выполняться ближней версией команды ret. Перед возвратом необходимо установить регистры процессора:

Регистр Описание содержимого регистра
AX Код возврата:Abort_Device_Load не загружать виртуальный драйвер;Abort_Win386_Load не загружать Windows;Device_Load_Ok можно продолжать процедуру инициализации и загрузки драйвера в память;No_Fail_Message это значение можно комбинировать со значениями Abort_Device_Load и Abort_Win386_Load, в этом случае на экран не выдается сообщение об аварийном завершении загрузки драйвера или операционной системы Windows
BX Указатель на массив, содержащий номера физических страниц памяти, зарезервированных для исключительного использования виртуальным драйвером. Последний элемент массива должен содержать нулевое значение.Под указателем здесь понимается смещение в сегменте инициализации реального режимаЕсли страницы физической памяти не резервируются, регистр BX должен содержать нулевое значение
EDX 32-разрядное значение, которое будет передано через регистр EDX процедуре инициализации защищенного режима, вызываемой по сообщению Sys_Critical_Init (инициализация в защищенном режиме будет рассмотрена позже)
SI Указатель на массив структур данных, состоящих из двойного слова и слова. Двойное слово содержит указатель на блок памяти, слово - размер этого блока памяти. Последний элемент массива должен содержать нулевое значение.Описанные таким образом блоки памяти создаются для каждой запускаемой виртуальной машины.Если блоки памяти не резервируются, в регистр SI следует записать нулевое значение
На этапе инициализации в реальном режиме можно пользоваться сервисом реального режима. Напомним, что адрес соответствующей точки входа передается через регистр ECX при вызове процедуры инициализации реального режима.

Вызов сервиса выполняется следующим образом:

mov ax, Service call cs:[ecx]

где Service - код сервиса.

Для кода сервиса возможны следующие значения:

Код сервиса Описание
0000hGet_Profile_String Получение строки из файла system.ini.В DS:SI должен находиться указатель на строку имени секции или 0 для секции [386Enh].В DS:DI необходимо записать адрес имени, а в ES:DX - адрес строки, которая будет использована по умолчанию.На выходе ES:DX будет содержать адрес строки, прочитанной из файла конфигурации или адрес строки по умолчанию, если указанные раздел или имя не найдены
0001hGet_Next_Profile_String Получение следующего значения, используется в том случае, если для одного имени указано несколько разных значений
0003hGet_Profile_Boolean Получение значения типа BOOL из файла system.ini.В ECX нужно записать значение по умолчанию (0 или 0FFFFFFFFh). В DS:SI должен находиться указатель на строку имени секции или 0 для секции [386Enh].В DS:DI необходимо записать адрес имени.Прочитанное из файла конфигурации значение записывается в регистр ECX
0004hGet_Profile_Decimal_Int Аналогично предыдущему, но возвращается целое значение, преобразованное из десятичного формата
0005hGet_Profile_Hex_Int Аналогично предыдущему, но возвращается целое значение, преобразованное из шестнадцатиричного формата
<


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

Теперь мы займемся вторым этапом инициализации, который выполняется в защищенном режиме.

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

При вызове управляющей процедуре передается системное управляющее сообщение (system control message). В драйвере необходимо предусмотреть обработку некоторых или всех таких сообщений (в зависимости от назначения драйвера).

На втором этапе инициализации виртуальному драйверу по очереди передаются три инициализирующих системных управляющих сообщения: Sys_Critical_Init, Device_Init и Init_Complete.

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

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

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

Как организовать обработку этих и других сообщений?



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

Вот пример управляющей процедуры нашего драйвера VXDSRV, который мы рассмотрим позже:

BeginProc VXDSRV_Control ; Процедура системной критической инициализации Control_Dispatch Sys_Critical_Init, VXDSRV_Sys_Crit_Init clc ; признак успешного завершения ret EndProc VXDSRV_Control

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

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

Приведем исходный текст процедуры системной критической инициализации драйвера VXDSRV:

VXD_ICODE_SEG BeginProc VXDSRV_Sys_Crit_Init

; Устанавливаем фильтр для прерывания int 21h mov eax, 21h mov esi, offset32 V86_Int21_Handler VMMcall Hook_V86_Int_Chain

clc ; признак успешного завершения ret EndProc VXDSRV_Sys_Crit_Init VXD_ICODE_ENDS

Эта процедура расположена в сегменте инициализации защищенного режима, который будет удален из памяти после завершения второго этапа инициализации. Она добавляет обработчик в цепочку обработчиков прерывания INT 21h с помощью сервиса Hook_V86_Int_Chain. При этом указывается адрес добавляемого обработчика - смещение функции V86_Int21_Handler.

Макрокоманда VMMcall служит для вызова сервиса и будет описана позже.

Итак, подведем небольшой итог.

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

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

Инициализация выполняется в два этапа.

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

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


Содержание раздела