Отправка 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 драйвера, используйте следующую процедуру:
Из функции обратного вызова EvtDriverDeviceAdd драйвер вызывает WdfDeviceConfigureWdmIrpDispatchCallback для регистрации функции обратного вызова EvtDeviceWdmIrpDispatch .
Если целевой объект является очередью ввода-вывода родительского устройства, драйвер KMDF должен вызвать WdfPdoInitAllowForwardingRequestToParent , прежде чем вызывать WdfDeviceCreate. Если драйвер KMDF также предоставил функцию обратного вызова EvtDeviceWdmIrpPreprocess , платформа сначала вызывает эту функцию при поступлении IRP. После того как функция обратного вызова предварительно обработает запрос, она вызывает WdfDeviceWdmDispatchPreprocessedIrp для возврата IRP в платформу.
Платформа вызывает функцию обратного вызова EvtDeviceWdmIrpDispatch драйвера.
Из evtDeviceWdmIrpDispatch драйвер может вызывать WdfDeviceWdmDispatchIrpToIoQueue или WdfDeviceWdmDispatchIrp, но не оба. Драйвер KMDF имеет дополнительную возможность вызова ни того, ни из этих методов, а вместо этого завершить IRP или пометить его в ожидании.
Если драйвер KMDF установил флаг WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK и не включил гарантированный ход выполнения для целевой очереди ввода-вывода, платформа вызывает EvtIoInCallerContext драйвера, если он указан. После предварительной обработки запроса функция обратного вызова должна либо поместить его в очередь, вызвав WdfDeviceEnqueueRequest, либо завершить его, вызвав WdfRequestComplete.
Отправка предварительно обработанных irp
Чтобы отправить IRP из функции обратного вызова EvtDeviceWdmIrpPreprocess драйвера в определенную очередь ввода-вывода, используйте следующую процедуру:
- Драйвер регистрирует функцию обратного вызова EvtDeviceWdmIrpPreprocess , вызывая WdfDeviceInitAssignWdmIrpPreprocessCallback.
- Драйвер вызывает WdfPdoInitAllowForwardingRequestToParent , если целевой объект является очередью ввода-вывода родительского устройства.
- Из EvtDeviceWdmIrpPreprocess вызовите WdfDeviceWdmDispatchIrpToIoQueue с флагами , для которых задано значение WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP.
- Если драйвер установил флаг WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK и не включил гарантированный ход выполнения для целевой очереди ввода-вывода, платформа вызывает EvtIoInCallerContext драйвера, если он указан. После завершения предварительной обработки запроса функция обратного вызова должна либо поместить его в очередь, вызвав WdfDeviceEnqueueRequest, либо завершить его, вызвав WdfRequestComplete.