Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
199
Добавлен:
20.02.2016
Размер:
110.59 Кб
Скачать

[10.2.2.1] Системная очередь запросов irp (System Queuing)

Простейший способ, с помощью которого драйвер может организовать очередь IRP – использовать Системную Очередь. Для этого драйвер предоставляет диспетчерскую точку входа StartIo (DriverObject->DriverStartIo). При получении пакета IRP, который необходимо поставить в Системную Очередь, такой пакет необходимо пометить как отложенный с помощью вызова IoMarkIrpPending(), а затем вызвать функцию IoStartPacket().

VOID IoStartPacket(IN PDEVICE_OBJECTDeviceObject,

IN PIRP Irp,

IN PULONG Key,

IN PDRIVER_CANCEL CancelFunction);

DeviceObject: Указатель на устройство, которому направлен запрос в/в

Irp: Указатель на пакет IRP, описывающий запрос в/в

Key: Необязательный указатель на значение, определяющее позицию в очереди IRP, в которую будет вставлен пакет IRP. Если указатель NULL, IRP помещается в конец очереди.

CancelFunction: Необязательный указатель на функцию – точку входа драйвера, которая будет вызвана при отмене данного запроса в/в диспетчером в/в.

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

При выборке очередного пакета IRP из очереди, если очередь не пуста, для очередного IRP будет вызвана функция StartIo. Функция имеет такой же прототип, как и все диспетчерские функции, но вызывается в случайном контексте потока на уровне IRQL DISPATCH_LEVEL:

NTSTATUS StartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp).

Структура функции StartIo практически такая же, как у диспетчерской функции, не использующей организацию очередей, за двумя важными исключениями:

  • StartIo вызывается в случайном контексте потока на уровне IRQL DISPATCH_LEVEL. Поэтому необходимо: а) соблюдать все ограничения для IRQL DISPATCH_LEVEL; б) не использовать метод передачи буфера Neither. Такой метод передачи предполагает знание контекста памяти процесса, из которого был инициирован запрос в/в (см. лекцию 7 п.[7.3] “Описание Буфера Данных”).

  • Какой бы ни был результат обработки пакета IRP, после завершения обработки IRP StartIo обязана вызвать функцию IoStartNextPacket()для указания диспетчеру в/в выбрать из системной очереди очередной пакет IRP (т.е. вызвать для него StartIo) сразу после завершения StartIo для текущего пакета.

Прототип функции IoStartNextPacket():

VOID IoStartNextPacket(IN PDEVICE_OBJECTDeviceObject, IN BOOLEANCancelable);

DeviceObject:Указатель на устройство, для которого необходимо выбрать следующий пакет из системной очереди IRP.

Cancelable:Указывает, может ли выбираемый из очереди пакет IRP быть отменен в процессе обработки. Если при вызове IoStartPacket() была указана ненулевая функция отмены, параметр Cancelable обязан быть равным TRUE.

Вместо IoStartNextPacket() может быть использована функция IoStartNextPacketByKey():

VOID IoStartNextPacketByKey(IN PDEVICE_OBJECTDeviceObject,

IN BOOLEAN Cancelable, IN ULONGKey);

В этом случае из очереди будет выбран очередной пакет IRP с заданным значением Key (это значение могло быть установлено при помещении пакета в очередь при вызове IoStartPacket()).

При использовании системной очереди диспетчер в/в отслеживает, когда данный объект-устройство свободен или занят обработкой очередного IRP. Это осуществляется с помощью специального объекта ядра Очередь Устройства (Device Queue Object, тип – структура KDEVICE_QUEUE), помещенного внутрь объекта-устройство в поле DeviceQueue. Поле DeviceQueue.Busy устанавливается диспетчером в/в равным TRUE непосредственно перед вызовом функции StartIo, и FALSE, когда вызвана функция IoStartNextPacket(ByKey)(), а системная очередь не содержит пакетов IRP для данного устройства. При обработке очередного IRP указатель на него находится в объекте-устройстве в поле CurrentIrp.

Соседние файлы в папке Лабы по драйверам