Функции загрузки/выгрузки драйвера
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

WDM-драйверы отличаются от унаследованных драйверов тем, что должны содержать дополнительные точки входа для поддержки PnP. Приведем список точек входа и кратко охарактеризуем их назначение.

NTSTATUS DriverEntry(

IN PDRIVER_OBJECT DriverObject, // указатель на объект драйвера

IN PUNICODE_STRING RegistryPath) // путь к подразделу регистра,

// относящегося к драйверу

Эта функция выполняется при загрузке драйвера операционной системой. В WDM-драйверах на DriverEntry возложены обязанности по регистрации всех остальных точек входа драйвера.

NTSTATUS AddDevice(

IN PDRIVER_OBJECT DriverObject, // указатель на объект драйвера

IN PDEVICE_OBJECT PhysicalDeviceObject) // указатель на родительский PDO

В поддерживающих PnP драйверах через эту точку входа менеджер PnP посылает драйверу уведомление об обнаружении устройства, за которое должен отвечать драйвер. Функция AddDevice должна создать объект устройства с помощью вызова IoCreateDevice и при необходимости присоединить его к стеку устройств вызовом IoAttachDeviceToDeviceStack.

NTSTATUS DriverUnload(

IN PDRIVER_OBJECT DriverObject) // указатель на объект драйвера

Вызывается при выгрузке драйвера. В этой функции должны осво­бождаться все затребованные драйвером ресурсы. Драйверы WDM-модели выполняют эти действия в обработчике запросов IRP_MJ_PNP с субкодом IRP_MN_REMOVE_DEVICE, то есть при удалении устройства из системы.

Функции обработки запросов/прерываний

Следует выделить отдельный класс точек входа драйвера, которые предназначены для обработки IRP-пакетов с различными кодами операций. Эти точки входа регистрируются при загрузке драйвера в функции DriverEntry. Регистрация производится путем заполнения элементов массива MajorFunction адресами диспетчеризуемых функций. Индексом в этом массиве являются коды IRP_MJ_XXX, то есть описанные числами типы пакетов IRP. Диспетчер ввода/вывода, ориентируясь на заполнение этого массива, вызывает нужные функции драйвера.

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

Стандартный прототип таких функций обработки:

NTSTATUS IRPControl(

IN PDEVICE_OBJECT DeviceObject, // указатель на объект устройства

IN PIRP Irp) // указатель на пакет IRP

Функции обработки пакетов IRP

Функции, адреса которых записаны в массиве MajorFunctions, вызываются диспетчером ввода/вывода для обработки соответствующих запросов от клиентского драйвера (пользовательских приложений или модулей уровня ядра). Эти запросы оформляются в виде специальных структур – IRP пакетов.

При любом запросе Диспетчер формирует IRP. Память для структуры IRP выделяется в нестраничной памяти. В IRP записывается код операции ввода вывода. Пакет IRP состоит из заголовка (рис. 2.3), который имеет постоянный размер и стека IRP (рис. 2.4). Стек имеет переменную длину.

Заголовок IRP пакета:

Поле IoStatus типа IO _ STATUS _ BLOCK содержит два подполя

Status - значение, которое устанавливает драйвер после обработки пакета.

В Information - чаще всего число переданных или полученных байт.

Поле AssociatedIrp . SystemBuffer типа void * содержит указатель на системный буфер для случая если устройство поддерживает буферизованный ввод/вывод.

Поле MdlAddress типа PMDL содержит указатель на MDL список, если устройство поддерживает прямой ввод вывод.

Поле UserBuffer типа void * содержит адрес пользовательского буфера для ввода/вывода.

Поле Cancel типа BOOLEAN - это индикатор того, что пакет IRP должен быть аннулирован.

 

Рис. 2.3. Заголовок IRP-пакета

 

Стек IRP пакета

Основное значение ячеек стека IRP пакета состоит в том, чтобы хранить функциональный код и параметры запроса на ввод/вывод. Для запроса, который адресован драйверу самого нижнего уровня, соответствующий IRP пакет имеет только одну ячейку стека. Для запроса, который послан драйверу верхнего уровня, Диспетчер ввода/вывода создает пакет IRP с несколькими стековыми ячейками – по одной для каждого FDO.

Каждая ячейка стека IRP содержит:

MajorFunction типа UCHAR – это код, описывающий назначение операции

MinorFunction типа UCHAR – это код, описывающий суб-код операции

DeviceObject типа PDEVICE _ OBJECT – это указатель на объект устройства, которому был адресован данный запрос IRP

FileObject типа PFILE _ OBJECT – файловый объект для данного запроса

Диспетчер ввода/вывода использует поле MajorFunction для того, чтобы извлечь из массива MajorFunction нужную для обработки запроса процедуру.

 

Рис. 2.4 Стек IRP-пакета

 

Функция обработки пакетов IRP _ MJ _ DEVICE _ CONTROL

Эта функция позволяет обрабатывать расширенные запросы от клиентов пользовательского режима. Такой запрос может быть сформирован посредством вызова функции DeviceIoControl. Каждый IOCTL запрос имеет свой код. Этот код передается как параметр функции DeviceIoControl. Код IOCTL – это 32-битное число.

Запросы IOCTL служат чаще всего для обмена данными между драйвером и приложением. Для передачи данных в Windows предусмотрены 4 способа:

METHOD_BUFFERED

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

METHOD_IN_DIRECT и METHOD_OUT_DIRECT

Необходимые страницы пользовательского буфера загружаются с диска в оперативную память и блокируются. Используются MDL-списки для доступа к буферу пользователя.

METHOD_NEITHER

При данном методе передачи не производится проверка доступности памяти, не выделяются промежуточные буфера и не создаются MDL. В пакете IRP передаются виртуальные адреса буферов в пространстве памяти инициатора запроса ввода/вывода.

Функция обработки пакетов IRP _ MJ _ READ

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

Функция обработки пакетов IRP _ MJ _ PNP

Данная функция должна обрабатывать запросы от менеджера PnP.

Функция обработки пакетов IRP _ MJ _ POWER

Данная функция должна обрабатывать запросы от менеджера питания.

ISR

Данная точка входа вызовется когда произойдет прерывание, на которое зарегистрирована эта ISR функция. Вызов может произойти в любом контексте: как ядра, так и пользовательского процесса. Здесь драйвер может либо дожидаться следующего прерывания либо запросить отложенный вызов процедуры DPC (Deferred Procedure Call).

Дата: 2019-12-22, просмотров: 241.