[Previous] [Next]

Глава 3

Простой драйвер "в-стиле-NT": Example.sys

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

Первые из них, драйверы пользовательского режима, представляют собой обычный программный код, как правило, оформленный в хорошо всем знакомые динамически загружаемые библиотеки (DLL). Эти драйверы стеснены в обращении к системным ресурсам и опираются в своей работе на модули режима ядра, с которыми они тесно сотрудничают. Так устроен пакет проектирование драйверов WinDriver от фирмы Jungo Ltd, в котором клиентские приложения через функции пользовательского режима (библиотеку функций WinDriver UserMode Library, являющуюся, по сути, драйвером пользовательского режима) общаются с кодом режима ядра (модулем WinDriver Kernel).

В данной книге рассматриваются только лишь драйверы второго семейства — драйверы режима ядра. Программирование в режиме ядра имеет свои специфические особенности. В частности, в качестве библиотечных функций (типа привычных malloc и free) в режиме ядра применяются системные вызовы (например, ExAllocatePool и ExFreePool). Более подробно вопросы программирования в режиме ядра будут рассмотрены в главе 7. Пока что кратко рассмотрим на примере простого драйвера Example.sys, как организованы драйверы режима ядра и как происходит связь с ними из приложений пользовательского режима.

Приведенный ниже код драйвера Example.sys является завершенным драйвером, который готов к компиляции и использованию в операционной системе в качестве тестового примера. По своей сути, приведенный код не может быть полноценным WDM драйвером (в силу отсутствия в нем некоторых основных рабочих процедур драйверов PnP устройств), хотя и может быть успешно скомпилирован средствами Visual С или DDK с WDM директивами. Драйвер Example.sys более подходит под описание "монолитный драйвер в-стиле-NT", так что он вполне подойдет в качестве заготовки для экспериментов, которые будут над ним выполнены в последующих главах.

Перед тем, как перейти непосредственно к рассмотрению примера, следует сделать одно важное замечание. Наиболее простое и одновременно весьма точное определение драйвера режима ядра гласит: драйвер — это DLL режима ядра. В самом деле, драйвер реализован как набор функций, каждая из которых предназначена для реализации отдельного типа обращений к драйверу со стороны Диспетчера ввода/вывода. Экспорт этих функций выполняется путем их регистрации в процедуре, стандартной для всех драйверов, — DriverEntry. Драйвер может быть загружен и выгружен, а для выполнения действий по инициализации или освобождению ресурсов драйвер должен зарегистрировать соответствующие рабочие функции.

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