[Previous] [Next]

Процедуры инициализации драйвера и очистки

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

Процедура DriverEntry

Диспетчер ввода/вывода вызывает данную процедуру при загрузке драйвера. Возможно, это произойдет в процессе загрузки операционной системы, но драйвер может быть загружен и динамически в любое время, как это было сделано с драйвером Example.sys в главе 3. Процедура DriverEntry решает первоочередные задачи, в частности, регистрацию в специальном массиве адресов других драйверных процедур (для того, чтобы Диспетчер ввода/вывода имел возможность позже производить их вызов по адресу). В случае если драйвер не работает по модели WDM (legacy драйвер, драйвер "в-стиле-NT"), то в этой же начальной процедуре можно провести локализацию оборудования, которое будет обслуживать драйвер, выделить или подтвердить использование аппаратных ресурсов (портов ввода/вывода, прерываний, каналов DMA) и предоставить имя, видимое всей остальной системе, для каждого обнаруженного устройства. Для WDM драйверов, поддерживающих спецификацию PnP, процесс определения аппаратных ресурсов откладывается на более позднее время и выполняется драйверной процедурой AddDevice.

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

Процедура ре-инициализации

Некоторые драйверы, по природе обслуживаемого ими устройства, иногда не могут завершить процесс инициализации во время работы DriverEntry. Это может иметь место, если драйвер зависит от других драйверов или системных служб, которые еще не загружены к моменту вызова DriverEntry. Такого типа драйвера должны сделать запрос определенного вида, чтобы их инициализация была отложена. Отложенная инициализация будет выполнена вызовом процедуры ре-инициализации ReInitialize, адрес которой необходимо сообщить во время работы DriverEntry вызовом IoRegisterDriverReinitialization, см. таблицу 8.2.

Процедура выгрузки Unload

Диспетчер ввода/вывода выполняет вызов драйверной процедуры Unload в случае, если драйвер выгружается динамически, то есть не в связи с откатом (завершением работы) операционной системы. Эта процедура должна выполнить действия, обратные работе DriverEntry, так чтобы не осталось "числящихся" за драйвером системных ресурсов. Эти действия включают удаление системного имени устройства и символьной ссылки, которые были предоставлены во время инициализации, объекта прерывания, если он был задействован, занятых областей памяти — поскольку за их удаление никто, кроме самого драйвера, в режиме ядра не отвечает. В драйверах WDM удаление ресурсов устройств (включая имена) выполняется при удалении каждого устройства (если драйвер обслуживает несколько устройств) в процессе выполнения RemoveDevice.

Возможно, legacy драйверам имеет смысл в пределах данной процедуры побеспокоиться о судьбе IRP пакетов, обработка которых не была завершена, и DPC объектов, которые еще находятся в системной DPC очереди.

Процедура Shutdown

Возможно, это прозвучит неожиданно, но процедура Unload не вызывается при выполнении подготовки системы к завершению ее работы (откате). Поскольку система закончит свою работу в любом случае, то действия, которые следовало бы непременно выполнить в процедуре Unload, здесь никого не волнуют, и действия про очистки не требуются. Вместо этого, Диспетчер ввода/вывода привлекает к работе драйверную процедуру Shutdown для того, чтобы предоставить драйверу возможность оставить устройство в приемлемом состоянии покоя после того, как операционная система перестанет функционировать.

Процедура обратного вызова Bugcheck

В том случае, если драйверу необходимо получить управление при крахе системы, он должен реализовать callback-процедуру Bugcheck. Эта процедура, при должной ее регистрации, будет вызвана ядром операционной системы в соответствующем месте выполнения 'crash'-процесса — сколь ни противоречиво звучит эта фраза.