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

       

Процедура StartIo


Выполняя регистрацию рабочей процедуры StartIo, драйвер соглашается участвовать в процессе, называющемся System Queuing, то есть создание очередей необработанных запросов при помощи системных средств &#8212 в отличие от Driver Queuing&#8212 ведение учета необработанных запросов средствами собственно драйвеpa (Для создания и ведения внутренних очередей драйверы используют вызовы KeInitalizeDeviceQueue

и прочие Ke...Queue).

В том случае, если какая-либо из рабочих процедур (например, обработки запросов Read-Write) не может завершить обработку запроса сразу, то она помечает текущий IRP пакет как 'pending' при помощи вызова, а на самом деле &#8212 макроопределения (см. файлы wdm.h или ntddk.h) IoMarkIrpPending, таблица 9.12. После этого она делает вызов IoStartPacket и возвращает управление Диспетчеру ввода/вывода с кодом STATUS_PENDING.

В результате вызова IoStartPacket Диспетчер ввода/вывода вызывает драйверную процедуру StartIo или, если устройство занято (то есть уже существует очередь необработанных пакетов IRP), помещает очередной пакет с состоянием 'pending' в очередь необработанных запросов. Таким образом, Диспетчер ввода/вывода выполняет сериализацию IRP запросов, вызывая рестарт ввода/вывода только по окончании обработки предыдущего запроса.

Как правило, процедура StartIo организует внутреннюю сортировку поступающих в нее IRP пакетов по кодам IRP_MJ_Xxx (например, обычным оператором 'switch'). Завершается работа StartIo тем, что текущий IRP пакет помечается как обработанный вызовом IoCompleteRequest (таблица 9.10), после чего выполняется вызов IoStartNextPacket, что побуждает Диспетчера ввода/вывода вызывать StartIo снова &#8212 для следующего из оставшихся в очереди IRP пакетов.

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


( поскольку он может быть сделан только программным кодом уровня DISPATCH_LEVEL). Этот вызов и запускает обработку помещенных в очередь IRP пакетов, побуждая Диспетчера ввода/вывода вызывать процедуру StartIo. Аналогично, вместо автоматического запуска обработки следующего IRP пакета в конце процедуры StartIo, как было указано выше, можно запускать следующую операцию ввода/вывода также по сигналу прерывания от устройства.

Размещение необработанных пакетов в очереди производится на принципах FIFO, то есть в конец очереди. Однако можно изменить это правило, задавая определенные значения параметра Key в вызове IoStartPacket. Изменить порядок извлечения очередного необработанного пакета из очереди можно, задавая определенные значения параметра Key в вызове IoStartNextPacketByKey.

Процедура StartIo регистрируется во время работы DriverEntry записью ее адреса в поле DriverStartIo в структуре объекта драйвера (что похоже на регистрацию процедуры AddDevice).


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