將 IRP 分派至 I/O 佇列
[適用于 KMDF 和 UMDF]
架構型驅動程式可以動態指定傳入 IRP 的目標佇列。 若要將 IRP 分派至特定佇列,驅動程式必須呼叫 WdfDeviceWdmDispatchIrpToIoQueue 方法。
一般而言,驅動程式會從其EvtDeviceWdmIrpPreprocess或EvtDeviceWdmIrpIrpDispatch回呼函式呼叫WdfDeviceWdmDispatchToIoQueue。 為了獲得最佳效能,大部分驅動程式都不提供這兩個回呼函式。
注意 UMDF 驅動程式可以提供 EvtDeviceWdmIrpDispatch 回呼函式,但只有 KMDF 驅動程式可以提供 EvtDeviceWdmIrpPreprocess。
如果您的驅動程式已經提供 EvtDeviceWdmIrpPreprocess,您可以使用它來動態選取佇列。 如果沒有,請提供 EvtDeviceWdmIrpDispatch ,並從該回呼函式內呼叫 WdfDeviceWdmDispatchIrpToIoQueue 。
此外,您應該注意下列事項:
將 IRP 分派至 I/O 佇列的替代方法是 建立預設佇列 ,然後從佇列的處理常式內呼叫 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 可以動態分派至指定的佇列。
移至 EvtDeviceWdmIrpPreprocess 的 IRP 具有額外的堆疊位置。 移至 EvtDeviceWdmIrpDispatch 的 IRP (,而不需先前叫用 EvtDeviceWdmIrpPreprocess) 。
EvtDeviceWdmIrpPreprocess 不會協助傳送驅動程式定義的內容資訊,而 EvtDeviceWdmIrpDispatch 則不會。
分派非預處理器的 IRP
若要從驅動程式的 EvtDeviceWdmIrpDispatch 回呼函式分派 IRP,請使用下列程式:
從 其 EvtDriverDeviceAdd 回呼函式中,驅動程式會呼叫 WdfDeviceConfigureWdmIrpDispatchCallback 來註冊 EvtDeviceWdmIrpDispatch 回呼函式。
如果目標是父裝置的 I/O 佇列,KMDF 驅動程式必須先呼叫 WdfPdoInitAllowForwardingRequestToParent ,才能呼叫 WdfDeviceCreate。 如果 KMDF 驅動程式也提供 EvtDeviceWdmIrpPreprocess 回呼函式,架構會在 IRP 送達時先呼叫該函式。 在回呼函式預先處理要求之後,它會呼叫 WdfDeviceWdmDispatchPreprocessedIrp ,以將 IRP 傳回至架構。
架構會呼叫驅動程式的 EvtDeviceWdmIrpDispatch 回呼函式。
從 EvtDeviceWdmIrpDispatch內,驅動程式可以呼叫 WdfDeviceWdmDispatchIrpToIoQueue 或 WdfDeviceWdmDispatchIrp,但不能同時呼叫這兩者。 KMDF 驅動程式有其他選項可以呼叫這兩種方法,而是完成 IRP 或將其標示為擱置中。
如果 KMDF 驅動程式已設定WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK旗標,而且未針對目標 I/O 佇列啟用保證的向前進度,則架構會呼叫驅動程式的 EvtIoInCallerCoNtext,如果提供的話。 前置處理要求之後,回呼函式必須藉由呼叫 WdfDeviceEnqueueRequest 將它排入佇列,或藉由呼叫 WdfRequestComplete來完成它。
分派前置處理 IRP
若要將 IRP 從驅動程式的 EvtDeviceWdmIrpPreprocess 回呼函式分派至特定的 I/O 佇列,請使用下列程式:
- 驅動程式會藉由呼叫WdfDeviceInitAssignWdmIrpPreprocessCallback來註冊EvtDeviceWdmIrpPreprocessWdmPreprocess函式。
- 如果目標是父裝置的 I/O 佇列,驅動程式 會呼叫 WdfPdoInitAllowForwardingRequestToParent 。
- 從 EvtDeviceWdmIrpPreprocess呼叫 WdfDeviceWdmDispatchIrpToIoQueue , 並將 Flags 設定為 WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP。
- 如果驅動程式已設定WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK旗標,而且未針對目標 I/O 佇列啟用保證的向前進度,則架構會呼叫驅動程式的 EvtIoInCallerCoNtext。如果提供的話。 在回呼函式完成前置處理要求之後,它必須藉由呼叫 WdfDeviceEnqueueRequest 將它排入佇列,或藉由呼叫 WdfRequestComplete來完成它。