Программирование драйверов Windows

       

Набор рабочих процедур


Все драйверы обязаны поддерживать функцию, которая отвечает за обработку запроса с кодом IRP_MJ_CREATE, так как этот код генерируется в ответ на вызов пользовательского режима CreateFile. Без поддержки этого запроса пользовательское приложение не будет иметь никакой возможности получить дескриптор (handle) для доступа к драйверу устройства, а значит, и к самому устройству. Разумеется, должна существовать функция, обрабатывающая запрос с кодом IRP_MJ_CLOSE, который генерируется по обращению приложения к драйверу при помощи функции API пользовательского режима CloseHandle. Кстати заметить, вызов CloseHandle

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

Набор остальных поддерживаемых функций зависит от особенностей устройства, которое находится "под покровительством" драйвера. Таблица 8.7б показывает взаимосвязь между кодами запросов ввода/вывода и вызовами API пользовательского режима, которые приводят к их генерации. При написании многослойных драйверов следует помнить, что вышестоящий драйвер обязан поддерживать подмножество запросов нижестоящего драйвера (драйверов), так как запрос пользовательского приложения проникает в нижние слои только через вышестоящий драйвер.

Таблица 8.7б. Коды запросов IRP и функции API пользовательского режима



IRP коды Вызовы API пользовательского режима
IRP_MJ_CREATE CreateFile
IRP_MJ_CLEANUP Очистка ожидающих обработки пакетов IRP при закрытии дескриптора при отработке вызова CloseHandle
IRP_MJ_CLOSE CloseHandle
IRP_MJ_READ ReadFile
IRP_MJ_WRITE WriteFile
IRP_MJ_DEVICE_CONTROL DeviceIoControl
IRP_MJ_INTERNAL_DEVICE_CONTROL Действия по управлению устройством, доступные только для клиентов, работающих в режиме ядра (недоступно для вызовов пользовательского режима)
IRP_MJ_QUERY_INFORMATION Передача длины файла в ответ на вызов GetFileSize
IRP_MJ_SET_INFORMATION Установка длины файла по вызову SetFileSize
IRP_MJ_FLUSH_BUFFERS Запись или очистка служебных буферов при отработке вызовов (например):

FlushFileBuffers

FlushConsolelnputBuffer

PurgeComm

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

Рабочая процедура обычно может отслеживать состояние обработки запроса только с использованием пакета IRP. В том случае, если рабочая процедура использует какие-либо данные за пределами пакета IRP, драйвер должен обеспечить достаточно надежные меры по синхронизации доступа к этим данным. Это означает, что можно было бы использовать спин-блокировку для координации действий с другими процедурами, выполняющимися на уровне IRQL не выше DISPATCH_LEVEL. Для синхронизации доступа из процедур, выполняющихся на уровне кода обслуживания прерываний, следует использовать KeSyncronizeExecution.

Пакеты IRP являются данными коллективного пользования, хотя и с последовательным доступом. В частности, Диспетчер ввода/вывода использует поля объединения Parameters для того, чтобы завершить обработку запроса. Например, по окончании обработки буферизованного ввода/вывода, ему необходимо выполнить копирование данных из области памяти нестраничного пула в буфер, заданный пользовательским приложением.По завершении копирования Диспетчер ввода/вывода должен освободить буфер в нестраничном пуле. Одно из полей объединения (union) Parameters как раз указывает на этот буфер, и изменение кодом драйвера данного указателя приведет к нарушению работы системы.


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