Организация ввода-вывода. Драйверы WDM. Рощин А.В. - 59 стр.

UptoLike

Составители: 

59
указатель стека на один уровень вверх и продолжает работу. Если же код возврата
совпадает со значением STATUS_MORE_PROCESSING_REQUIRED, функция
IoCompleteRequest прерывает работу и возвращает управление тому, кто ее
вызвал. При этом пакет запроса ввода-вывода IRP оказывается в «подвешенном»
состоянии. Для вывода пакета из такого состояния драйвер, функция завершения
которого прервала
процесс «раскрутки» стека, выполнит эту дополнительную
обработку IRP и опять вызовет функцию IoCompleteRequest для продолжения
процесса завершения.
Следует отметить, что внутри функции завершения вызов функции
IoGetCurrentIrpStackLokation получает указатель на элемент стека, который был
текущим на момент вызова IoSetCompletionRoutine. В функции завершения
нельзя пользоваться содержимым элементов стека нижнего уровня. Во избежание
такого
соблазна функция IoCompleteRequest обнуляет большую часть полей
следующего элемента перед вызовом функции завершения.
3.16 Очереди запросов ввода-вывода
Бывает так, что драйвер получает пакет запроса ввода-вывода IRP, который
он не может обработать сразу. Диспетчерская функция может отвергнуть этот IRP
с кодом ошибки, или поместить его в очередь. Далее в драйвере
реализуется
логика взятия IRP из очереди и передачи его функции StartIo.
В принципе, организовать очередь IRP очень просто. Первый элемент
(якорь) списка включается в объект расширения устройства и инициализируется
функцией AddDevice:
typedef struct _DEVICE_EXTENSION {
LIST_ENTRY IrpQueue;
BOOLEAN DeviceBusy;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS AddDevice(…)
{
InitializeListHead(&pdx->IrpQueue);
указатель стека на один уровень вверх и продолжает работу. Если же код возврата
совпадает со значением STATUS_MORE_PROCESSING_REQUIRED, функция
IoCompleteRequest прерывает работу и возвращает управление тому, кто ее
вызвал. При этом пакет запроса ввода-вывода IRP оказывается в «подвешенном»
состоянии. Для вывода пакета из такого состояния драйвер, функция завершения
которого прервала процесс «раскрутки» стека, выполнит эту дополнительную
обработку IRP и опять вызовет функцию IoCompleteRequest для продолжения
процесса завершения.
     Следует отметить, что внутри функции завершения вызов функции
IoGetCurrentIrpStackLokation получает указатель на элемент стека, который был
текущим на момент вызова IoSetCompletionRoutine. В функции завершения
нельзя пользоваться содержимым элементов стека нижнего уровня. Во избежание
такого соблазна функция IoCompleteRequest обнуляет большую часть полей
следующего элемента перед вызовом функции завершения.


     3.16 Очереди запросов ввода-вывода
     Бывает так, что драйвер получает пакет запроса ввода-вывода IRP, который
он не может обработать сразу. Диспетчерская функция может отвергнуть этот IRP
с кодом ошибки, или поместить его в очередь. Далее в драйвере реализуется
логика взятия IRP из очереди и передачи его функции StartIo.
     В принципе, организовать очередь IRP очень просто. Первый элемент
(якорь) списка включается в объект расширения устройства и инициализируется
функцией AddDevice:
     typedef struct _DEVICE_EXTENSION {
      LIST_ENTRY IrpQueue;
      BOOLEAN DeviceBusy;
      } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
     NTSTATUS AddDevice(…)
      {
      …
      InitializeListHead(&pdx->IrpQueue);
      …
                                      59