Поделиться через


Отправка IRP в очереди операций ввода-вывода

[Применимо к KMDF и UMDF]

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

Как правило, драйвер вызывает WdfDeviceWdmDispatchIrpToIoQueue из функции обратного вызова EvtDeviceWdmIrpPreprocess или EvtDeviceWdmIrpDispatch. Для повышения производительности большинство драйверов не предоставляют обе функции обратного вызова.

примечание драйвер UMDF может предоставить функцию обратного вызова EvtDeviceWdmIrpDispatch, но только драйверы KMDF могут предоставлять EvtDeviceWdmIrpPreprocess.

Если драйвер уже предоставляет EvtDeviceWdmIrpPreprocess, его можно использовать для динамического выбора очереди. В противном случае укажите EvtDeviceWdmIrpDispatch и вызовите WdfDeviceWdmDispatchIrpToIoQueue в рамках этой функции обратного вызова.

Кроме того, следует учитывать следующее:

  • Альтернативным способом отправки IRP в очередь ввода-вывода является создать очередь по умолчанию, а затем из функции обработки очереди вызвать WdfRequestForwardToIoQueue. Этот метод доступен начиная с KMDF 1.0, но не работает хорошо с очередями на продвижение и в целом медленнее. Вместо этого рекомендуется использовать WdfDeviceWdmDispatchIrpToIoQueue.

  • При вызове WdfDeviceConfigureWdmIrpDispatchCallback для регистрации функции обратного вызова EvtDeviceWdmIrpDispatch драйвер должен установить параметр MajorFunction на один из следующих: IRP_MJ_DEVICE_CONTROL, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE. Хотя это требование не применяется к EvtDeviceWdmIrpPreprocess, только IRP этих типов можно динамически отправлять в указанные очереди.

  • IRP, которые отправляются в EvtDeviceWdmIrpPreprocess, имеют дополнительную позицию стека. IRPs, которые отправляются в EvtDeviceWdmIrpDispatch (без предыдущего вызова EvtDeviceWdmIrpPreprocess), не выполняются.

  • EvtDeviceWdmIrpPreprocess не упрощает отправку сведений о контексте, определенных драйвером, в то время как EvtDeviceWdmIrpDispatch.

Отправка непроцессированных IRP

Чтобы отправить IRP из функции обратного вызова драйвера EvtDeviceWdmIrpDispatch, используйте следующую процедуру:

  1. Из функции обратного вызова EvtDriverDeviceAdd драйвер вызывает WdfDeviceConfigureWdmIrpDispatchCallback для регистрации функции обратного вызова EvtDeviceWdmIrpDispatch.

    Если целевой объект — это очередь ввода-вывода родительского устройства, драйвер KMDF должен вызвать WdfPdoInitAllowForwardingRequestToParent перед вызовом WdfDeviceCreate. Если драйвер KMDF также предоставил функцию обратного вызова EvtDeviceWdmIrpPreprocess, фреймворк сначала вызывает ее при поступлении IRP. После предварительной обработки запроса функция обратного вызова вызывает WdfDeviceWdmDispatchPreprocessedIrp, чтобы вернуть IRP в фреймворк.

  2. Платформа вызывает функцию обратного вызова драйвера EvtDeviceWdmIrpDispatch.

  3. Из EvtDeviceWdmIrpDispatch драйвер может вызывать WdfDeviceWdmDispatchIrpToIoQueue или WdfDeviceWdmDispatchIrp, но не оба. Драйвер KMDF имеет дополнительную возможность не вызывать ни один из этих методов, а вместо этого завершать IRP или помечать его как ожидающий.

  4. Если драйвер KMDF установил флаг WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK и не включил гарантированное продвижение для целевой очереди ввода-вывода, фреймворк вызывает драйвера EvtIoInCallerContext, если указано. После предварительной обработки запроса функция обратного вызова должна поставить его в очередь, вызвав WdfDeviceEnqueueRequest, или завершить его вызовом WdfRequestComplete.

Отправка предварительно обработанных IRP

Чтобы отправить IRPs из функции обратного вызова драйвера EvtDeviceWdmIrpPreprocess в определенную очередь ввода-вывода, используйте следующую процедуру.

  1. Драйвер регистрирует функцию обратного вызова EvtDeviceWdmIrpPreprocess путем вызова WdfDeviceInitAssignWdmIrpPreprocessCallback.
  2. Драйвер вызывает WdfPdoInitAllowForwardingRequestToParent, если цель — очередь ввода-вывода родительского устройства.
  3. Из EvtDeviceWdmIrpPreprocess вызовите WdfDeviceWdmDispatchIrpToIoQueue, установив флаг в значение WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP.
  4. Если драйвер установил флаг WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK и не включил гарантированный прогресс для целевой очереди ввода-вывода, фреймворк вызывает EvtIoInCallerContext драйвера , если она предоставлена. После завершения предварительной обработки запроса функция обратного вызова должна либо поставить его в очередь вызовом WdfDeviceEnqueueRequest, либо завершить его вызовом WdfRequestComplete.