Создание VxD на Visual C++ без ассемблерных модулей Часть 3. Статические и динамические драйверы
Статические и динамические драйверы По способу загрузки VxD разделяются на статические — загружаемые один раз в процессе старта Windows и работающие до ее закрытия, и динамические
— загружаемые и выгружаемые по запросу системы и приложений.
Динамические VxD используются в тех случаях, когда постоянное
присутствие драйвера в системе необязательно, однако по понятной
причине они не могут участвовать в начальной инициализации системы.
Статические VxD могут участвовать в инициализации системы, однако не
могут быть выгружены в процессе ее работы. Порядок загрузки статических драйверов Статические
драйверы загружаются системой в определенном порядке при этом основные
драйверы должны загружаться первыми, а после этого — зависящие от них
драйверы более высокого уровня. Для этой процедуры каждый драйвер имеет
параметр Init Order — числовую константу,
определяющую место драйвера в списке загрузки, которая происходит в
порядке возрастания значений параметра. Системным драйверам назначены
определенные значения, отражающие их зависимость друг от друга. Если
порядок загрузки не имеет смысла — используется нулевое значение
параметра; такие драйверы загружаются после завершения инициализации
«номерных» VxD. Системные сообщения драйверу Система взаимодействует с драйвером путем передачи ему системных сообщений
о загрузке/выгрузке драйвера, а также при наступлении определенных
системных событий, которые могут потребовать вмешательства драйвера
(создание/удаление виртуальной машины, приложения, задачи (thread),
смена текущей виртуальной машины/задачи, перезагрузка системы,
появление нового устройства и т.п.). Для обработки системных сообщений каждый драйвер должен содержать диспетчер сообщений
— процедуру, которая получает управление при передаче сообщения
драйверу. Процедуре передается код сообщения и его параметры, после
завершения обработки процедура возвращает результат, определяющий
последующие действия системы. Сервисные функции драйвера Каждый драйвер, имеющий идентификатор, может поддерживать набор сервисных функций,
доступных для других VxD в системе. Если VxD представляет какое-либо
виртуальное устройство, эти функции служат для управления устройством
либо просто воплощают какие-либо операции, ради которых создавался
драйвер. Сервисные функции драйвера имеют номера начиная с нуля,
по которым их могут вызывать другие VxD. Драйвер предоставляет системе
таблицу адресов процедур — обработчиков функций, обращение к которым
происходит путем вызова процедуры по индексу из таблицы. Обязательна
для поддержки только функция с нулевым номером — Get Version (запрос
версии). Поддержка и назначение остальных функций оставлена на
усмотрение разработчика драйвера. Механизм вызова сервисных
функций использует идентификатор драйвера, по которому происходит поиск
нужного драйвера в системе. Поэтому драйверы, не имеющие
идентификатора, не могут быть вызваны для обработки сервисных функций. Интерфейс с прикладными программами Для
взаимодействия с прикладными программами VxD может предоставлять три
вида API (Application Program Interface — интерфейс прикладных
программ): - V86 API — для 16-разрядных приложений DOS (программ режима V86).
- PM API
— для 16-разрядных приложений Windows, которые до появления Windows 9x
назывались Protected Mode Applications (приложения защищенного режима).
- Win32 API — для приложений Win32.
Для
обработки запросов от 16-разрядных программ в драйвере
предусматриваются две различные функции — для запросов от виртуальных
машин DOS и для запросов от приложений Win16. Запросы от приложений
Win32 передаются в виде системных сообщений их общему диспетчеру. 16-разрядные приложения получают доступ к своим API посредством функции 0x1684 программного прерывания 2F,
которая возвращает адрес шлюза (gate) для вызова VxD. Поиск нужного
драйвера возможен как по идентификатору, так и по имени; поиск по имени
был введен позднее, поэтому документирован не во всех описаниях функции
int 2F. При выполнении вызова через шлюз
происходит переключение в 32-разрядный режим с сохранением всех
регистров вызвавшей виртуальной машины (клиента) в специальной
структуре, после чего управление передается соответствующей процедуре
обработки в VxD. При возврате происходит восстановление значений
регистров, которые могут быть модифицированы процедурой обработки. Приложения Win32 получают доступ к API посредством функции CreateFile,
загружающей VxD, если он динамический, и открывающей его интерфейс.
Поиск драйвера происходит по имени драйвера, имени его файла либо по
имени ключа реестра, описывающего драйвер. Обращение к обработчику Win32 API в драйвере происходит при вызове приложением функции DeviceIoControl.
При этом выполняется переключение в режим ядра и передача диспетчеру
системных сообщений драйвера сообщения W32_DEVICEIOCONTROL. Для обмена
данными передаются два независимых указателя (буфер параметров и буфер
результата), которые могут ссылаться и на одну и ту же область памяти.
Если драйвер поддерживает механизм асинхронных (overlapped) операций,
фактическое завершение операции может происходить независимо от момента
возврата управления из диспетчера.
|