Beispiel für die Verwendung von E/A-Warteschlangen
Für jedes Gerät, das mit einem System verbunden ist und von einem bestimmten Treiber unterstützt wird, kann der Treiber die folgenden Kombinationen von E/ A-Warteschlangen und Anforderungshandlern verwenden:
Eine einzelne Standard-E/A-Warteschlange und ein einzelner Anforderungshandler, EvtIoDefault. Das Framework übermittelt alle Anforderungen des Geräts an die Standardwarteschlange und ruft den EvtIoDefault-Handler des Treibers auf, um jede Anforderung an den Treiber zu übermitteln.
Eine einzelne E/A-Standardwarteschlange und mehrere Anforderungshandler wie EvtIoRead, EvtIoWrite und EvtIoDeviceControl. Das Framework übermittelt alle Anforderungen des Geräts an die Standardwarteschlange. Er ruft den EvtIoRead-Handler des Treibers zum Übermitteln von Leseanforderungen, den EvtIoWrite-Handler zum Übermitteln von Schreibanforderungen und den EvtIoDeviceControl-Handler zum Übermitteln von Geräte-E/A-Steuerungsanforderungen auf.
Mehrere E/A-Warteschlangen, z. B. eine für Leseanforderungen und eine für Schreibanforderungen. Für jede Warteschlange stellt der Treiber nur einen Anforderungshandler bereit, da die Warteschlange nur einen Anforderungstyp empfängt.
Mehrere E/A-Warteschlangen mit jeweils mehreren Anforderungshandlern.
Beispielszenarien:
Eine einzelne sequenzielle E/A-Warteschlange
Wenn Sie einen Funktionstreiber für ein Laufwerk schreiben, das Lese- und Schreibanforderungen nur einzeln verarbeiten kann, benötigt der Funktionstreiber nur eine E/A-Warteschlange pro Gerät.
Der Treiber kann die Standard-E/A-Warteschlange verwenden, die das Framework erstellt, wenn der Treiber WdfIoQueueCreate aufruft und DefaultQueue in der WDF_IO_QUEUE_CONFIG-Struktur der Warteschlange auf TRUE festlegt. In der WDF_IO_QUEUE_CONFIG-Struktur sollte der Treiber auch Folgendes angeben:
WdfIoQueueDispatchSequential als Verteilermethode, sodass die Standard-E/A-Warteschlange E/A-Anforderungen synchron an den Treiber übermittelt.
Eine einzelne Ereignisrückruffunktion, EvtIoDefault, die alle E/A-Anforderungen empfängt.
Jedes Mal, wenn eine E/A-Anforderung in der Standard-E/A-Warteschlange des Treibers verfügbar ist, übermittelt das Framework die Anforderung an den Treiber, indem es den EvtIoDefault-Anforderungshandler des Treibers aufruft. Wenn eine andere Anforderung in der Warteschlange verfügbar wird, übermittelt das Framework sie erst, wenn der Treiber WdfRequestComplete für die zuvor übermittelte Anforderung aufruft .
Mehrere sequenzielle E/A-Warteschlangen und eine manuelle Warteschlange
Betrachten Sie ein Gerät mit seriellem Port, das die folgenden Merkmale aufweist:
Es kann gleichzeitig einen Lese- und einen Schreibvorgang ausführen.
Es können nicht mehrere Lese- oder Schreibvorgänge asynchron ausgeführt werden.
Es kann Geräte-E/A-Steuerungsanforderungen für status Informationen empfangen. Der Treiber des Geräts kann lange dauern, bis einige dieser Anforderungen abgeschlossen sind (z. B. eine Anforderung, auf eine status Änderung zu warten).
Ein Funktionstreiber für dieses Gerät kann mehrere sequenzielle E/A-Warteschlangen pro Gerät verwenden. Der Treiber ruft WdfIoQueueCreate dreimal auf: einmal, um eine Standardwarteschlange zu erstellen, und zweimal, um zwei zusätzliche E/A-Warteschlangen zu erstellen. In der WDF_IO_QUEUE_CONFIG-Struktur für jede dieser Warteschlangen sollte der Treiber Folgendes angeben:
WdfIoQueueDispatchSequential als Verteilmethode für jede Warteschlange, sodass das Framework E/A-Anforderungen synchron an den Treiber übermittelt.
Ein anderer Anforderungshandler für jede Warteschlange (EvtIoDefault, EvtIoRead und EvtIoWrite), der die E/A-Anforderungen der Warteschlange empfängt.
Nach dem Aufrufen von WdfIoQueueCreate kann der Treiber WdfDeviceConfigureRequestDispatching zweimal aufrufen, um alle Leseanforderungen an eine der zusätzlichen Warteschlangen und alle Schreibanforderungen an die andere weiterzuleiten.
Mit dieser Konfiguration empfängt die EvtIoDefault-Rückruffunktion der Standard-E/A-Warteschlange des Geräts nur die Anforderungen der Geräte-E/A-Steuerung für status Informationen.
Wenn der Treiber eine status-Anforderung für einen längeren Zeitraum speichern muss, kann er eine vierte Warteschlange erstellen und WdfIoQueueDispatchManual als Verteilmethode angeben. Wenn der Treiber eine Anforderung für Informationen empfängt, auf die er warten muss, kann er die Anforderung in dieser zusätzlichen Warteschlange platzieren, bis die status Informationen verfügbar sind. Anschließend kann der Treiber die Anforderung aus der Warteschlange abrufen und abschließen. In der Zwischenzeit kann die Standardwarteschlange eine weitere Anforderung an den Treiber übermitteln.
Eine einzelne parallele E/A-Warteschlange
IDE-Datenträgercontroller können einige E/A-Vorgänge überlappen, andere jedoch nicht. Während ein Controller beispielsweise einen Lese- oder Schreibvorgang auf einem Datenträger verarbeitet, kann er einen Seek-Befehl an einen anderen Datenträger senden. Auf der anderen Seite werden mehrere gleichzeitige Lese- und Schreibbefehle nicht unterstützt.
Ein Funktionstreiber für diesen Controller muss jede E/A-Anforderung untersuchen. Wenn der Treiber einen Seek-Befehl empfängt, muss er ermitteln, ob der Seek-Befehl verarbeitet werden kann. Der Seek-Befehl kann nicht verarbeitet werden, wenn:
Das angegebene Laufwerk ist bereits ausgelastet.
Ein Datenträgerlaufwerk wird formatiert, und daher können keine anderen Laufwerke aktiv sein.
Für jedes Gerät, das mit dem Controller verbunden ist, kann der Treiber WdfIoQueueCreate aufrufen, um eine Standard-E/A-Warteschlange zu erstellen. In der WDF_IO_QUEUE_CONFIG-Struktur für jede dieser Warteschlangen sollte der Treiber Folgendes angeben:
WdfIoQueueDispatchParallel als Verteilermethode für jede Warteschlange, sodass das Framework E/A-Anforderungen asynchron an den Treiber übermittelt.
Eine EvtIoDefault-Ereignisrückruffunktion für jede Warteschlange, die die E/A-Anforderungen der Warteschlange empfängt.
Mit dieser Konfiguration wird jedem Gerät eine einzelne, parallele E/A-Warteschlange zugewiesen. Der Treiber muss jede E/A-Anforderung untersuchen, die das Framework aus jeder E/A-Warteschlange übermittelt. Wenn der Treiber die Anforderung sofort verarbeiten kann, tut er dies. Andernfalls ruft der Treiber WdfIoQueueStop auf, wodurch das Framework die Übermittlung von Anforderungen beendet, bis der Treiber WdfIoQueueStart aufruft.
Mehrere parallele E/A-Warteschlangen
Ein SCSI-Hostadapter ist ein Beispiel für ein Gerät, das asynchrone, überlappende E/A-Vorgänge unterstützt. Bis zu 32 Geräte können an den Adapter angeschlossen werden. Betrachten Sie ein System mit der folgenden Konfiguration:
Einige geräte, die mit dem SCSI-Adapter verbunden sind, unterstützen die "erneute Auswahl", andere nicht. Wenn ein SCSI-Gerät die erneute Auswahl unterstützt, kann das Gerät während eines E/A-Vorgangs den Adapter vorübergehend freigeben, damit der Adapter ein anderes Gerät bedienen kann. Das erste Gerät wählt sich später neu aus, um seinen Betrieb abzuschließen.
Der SCSI-Adapter verwendet Hardwarepostfächer, um Anforderungen und Antworten zwischen dem Treiber und den Geräten zu übergeben. Wenn ein Gerät für eine Anforderung bereit ist, aber keine Postfächer verfügbar sind, muss das Gerät warten.
Um eine optimale Leistung zu erzielen, sollte der Funktionstreiber für diesen SCSI-Hostadapter E/A-Anforderungen vom Framework empfangen, sobald sie verfügbar sind. Der Treiber muss jede Anforderung untersuchen und feststellen, ob sie sofort gestartet werden kann oder verschoben werden muss, bis das Gerät und die Ressourcen (z. B. Postfachspeicher) verfügbar sind.
Der Treiber sollte wahrscheinlich mehrere parallele E/A-Warteschlangen verwenden. Für jedes Gerät, das mit dem Adapter verbunden ist, ruft der Treiber WdfIoQueueCreate auf , um eine Standard-E/A-Warteschlange zu erstellen. In der WDF_IO_QUEUE_CONFIG-Struktur für jede dieser Warteschlangen sollte der Treiber Folgendes angeben:
WdfIoQueueDispatchParallel als Verteilermethode für jede Warteschlange, sodass das Framework E/A-Anforderungen asynchron an den Treiber übermittelt.
Eine EvtIoDefault-Ereignisrückruffunktion für jede Warteschlange, die die E/A-Anforderungen der Warteschlange empfängt.
Die EvtIoDefault-Rückruffunktion jeder E/A-Warteschlange muss die E/A-Anforderungen der Warteschlange während der Übermittlung untersuchen und bestimmen, ob jede sofort gewartet werden kann. Wenn das Gerät und die Systemressourcen verfügbar sind, startet der Treiber den E/A-Vorgang. Wenn das Gerät oder die Ressourcen nicht verfügbar sind, muss der Treiber WdfIoQueueStop aufrufen, um die Übermittlung zusätzlicher Anforderungen zu beenden, bis die aktuelle Anforderung verarbeitet werden kann.
Optional kann der Treiber WdfIoQueueCreate aufrufen, um zusätzliche Warteschlangen für jedes Gerät zu erstellen. Anschließend kann der Treiber WdfRequestForwardToIoQueue aufrufen, um einige Arten von Anforderungen erneut an die zusätzlichen Warteschlangen zu senden. Wenn das Framework Anforderungen aus einer zusätzlichen Warteschlange übermittelt, kann der Treiber bei Bedarf WdfIoQueueStop in dieser Warteschlange anstelle der Standardwarteschlange aufrufen, wodurch die Anzahl oder art der Anforderungen, für die die Übermittlung verschoben wird, minimiert wird.