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


Отправка 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 , имеют дополнительное расположение стека. IrP, которые переходят к 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

Чтобы отправить IRP из функции обратного вызова 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.