Senden von IRPs an E/A-Warteschlangen
[Gilt für KMDF und UMDF]
Ein frameworkbasierter Treiber kann dynamisch eine Zielwarteschlange für eine eingehende IRP angeben. Um eine IRP an eine bestimmte Warteschlange zu senden, muss ein Treiber die WdfDeviceWdmDispatchIrpToIoQueue-Methode aufrufen.
In der Regel ruft ein Treiber WdfDeviceWdmDispatchIrpToIoQueue über die Rückruffunktion EvtDeviceWdmIrpPreprocess oder EvtDeviceWdmIrpDispatch auf. Um eine optimale Leistung zu erzielen, bieten die meisten Treiber nicht beide Rückruffunktionen.
Hinweis Ein UMDF-Treiber kann eine EvtDeviceWdmIrpDispatch-Rückruffunktion bereitstellen, aber nur KMDF-Treiber können EvtDeviceWdmIrpPreprocess bereitstellen.
Wenn Ihr Treiber bereits EvtDeviceWdmIrpPreprocess bereitstellt, können Sie damit eine Warteschlange dynamisch auswählen. Wenn nicht, geben Sie EvtDeviceWdmIrpDispatch an, und rufen Sie WdfDeviceWdmDispatchIrpToIoQueue in dieser Rückruffunktion auf.
Darüber hinaus sollten Sie Folgendes beachten:
Eine alternative Methode zum Senden eines IRP an eine E/A-Warteschlange besteht darin, eine Standardwarteschlange zu erstellen und dann aus dem Handler der Warteschlange WdfRequestForwardToIoQueue aufzurufen. Diese Technik ist ab KMDF 1.0 verfügbar, funktioniert jedoch nicht gut mit Vorwärtsstatuswarteschlangen und ist im Allgemeinen langsamer. Erwägen Sie stattdessen die Verwendung von WdfDeviceWdmDispatchIrpToIoQueue .
Wenn WdfDeviceConfigureWdmIrpDispatchCallback aufgerufen wird, um eine EvtDeviceWdmIrpDispatch-Rückruffunktion zu registrieren, muss der Treiber den MajorFunction-Parameter auf einen der folgenden Parameter festlegen: IRP_MJ_DEVICE_CONTROL, IRP_MJ_INTERNAL_DEVICE_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE. Diese Anforderung gilt zwar nicht für EvtDeviceWdmIrpPreprocess, aber nur IRPs dieser Typen können dynamisch an angegebene Warteschlangen verteilt werden.
IRPs, die zu EvtDeviceWdmIrpPreprocess wechseln, verfügen über einen zusätzlichen Stapelspeicherort. IRPs, die zu EvtDeviceWdmIrpDispatch (ohne vorherigen Aufruf von EvtDeviceWdmIrpPreprocess) gehen, nicht.
EvtDeviceWdmIrpPreprocess erleichtert das Senden von vom Treiber definierten Kontextinformationen nicht, während EvtDeviceWdmIrpDispatch dies tut.
Senden nicht vorverarbeiteter IRPs
Führen Sie das folgende Verfahren aus, um IRPs von der EvtDeviceWdmIrpDispatch-Rückruffunktion eines Treibers zu senden:
Über die Rückruffunktion EvtDriverDeviceAdd ruft der Treiber WdfDeviceConfigureWdmIrpDispatchCallback auf, um eine EvtDeviceWdmIrpDispatch-Rückruffunktion zu registrieren.
Wenn das Ziel die E/A-Warteschlange des übergeordneten Geräts ist, muss ein KMDF-Treiber WdfPdoInitAllowForwardingRequestToParent aufrufen, bevor er WdfDeviceCreate aufruft. Wenn ein KMDF-Treiber auch eine EvtDeviceWdmIrpPreprocess-Rückruffunktion bereitgestellt hat, ruft das Framework diese Funktion zuerst auf, wenn ein IRP eintrifft. Nachdem die Rückruffunktion die Anforderung vorverarbeitet hat, ruft sie WdfDeviceWdmDispatchPreprocessedIrp auf, um den IRP an das Framework zurückzugeben.
Das Framework ruft die Rückruffunktion EvtDeviceWdmIrpDispatch des Treibers auf.
In EvtDeviceWdmIrpDispatch kann der Treiber entweder WdfDeviceWdmDispatchIrpToIoQueue oder WdfDeviceWdmDispatchIrp aufrufen, aber nicht beide. Ein KMDF-Treiber hat die zusätzliche Möglichkeit, keine dieser Methoden aufzurufen und stattdessen die IRP abzuschließen oder ausstehend zu markieren.
Wenn ein KMDF-Treiber das flag WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK festgelegt hat und den garantierten Vorwärtsfortschritt für die Ziel-E/A-Warteschlange nicht aktiviert hat, ruft das Framework den EvtIoInCallerContext des Treibers auf, falls angegeben. Nach der Vorverarbeitung der Anforderung muss die Rückruffunktion sie entweder in eine Warteschlange stellen, indem sie WdfDeviceEnqueueRequest aufruft, oder sie durch Aufrufen von WdfRequestComplete abschließen.
Senden vorverarbeiteter IRPs
Führen Sie das folgende Verfahren aus, um IRPs von der EvtDeviceWdmIrpPreprocess-Rückruffunktion eines Treibers an eine bestimmte E/A-Warteschlange zu senden:
- Der Treiber registriert eine EvtDeviceWdmIrpPreprocess-Rückruffunktion , indem er WdfDeviceInitAssignWdmIrpPreprocessCallback aufruft.
- Der Treiber ruft WdfPdoInitAllowForwardingRequestToParent auf, wenn das Ziel die E/A-Warteschlange des übergeordneten Geräts ist.
- Rufen Sie in EvtDeviceWdmIrpPreprocessWdfDeviceWdmDispatchIrpToIoQueue auf, wobei Flags auf WDF_DISPATCH_IRP_TO_IO_QUEUE_PREPROCESSED_IRP festgelegt ist.
- Wenn der Treiber das WDF_DISPATCH_IRP_TO_IO_QUEUE_INVOKE_INCALLERCTX_CALLBACK-Flag festgelegt und den garantierten Vorwärtsfortschritt für die Ziel-E/A-Warteschlange nicht aktiviert hat, ruft das Framework den EvtIoInCallerContext des Treibers auf, falls angegeben. Nachdem die Rückruffunktion die Vorverarbeitung der Anforderung abgeschlossen hat, muss sie sie entweder in eine Warteschlange stellen, indem sie WdfDeviceEnqueueRequest aufruft, oder sie durch Aufrufen von WdfRequestComplete abschließen.