Abbrechen von E/A-Anforderungen
Der E/A-Vorgang eines Geräts (z. B. eine Anforderung zum Lesen mehrerer Blöcke von einem Datenträger) kann von einer Anwendung, dem System oder einem Treiber abgebrochen werden. Wenn der E/A-Vorgang eines Geräts abgebrochen wird, versucht der E/A-Manager, alle nicht verarbeiteten E/A-Anforderungen abzubrechen, die dem E/A-Vorgang zugeordnet sind. Die Treiber des Geräts können sich registrieren, um benachrichtigt zu werden, wenn der E/A-Manager versucht, E/A-Anforderungen abzubrechen, und die Treiber können die Anforderungen, die sie besitzen, abbrechen, indem sie sie mit einer status STATUS_CANCELLED abschließen.
Das Framework übernimmt einen Teil der Abbrucharbeit für frameworkbasierte Treiber. Wenn der E/A-Vorgang eines Geräts abgebrochen wird, führt das Framework die folgenden E/A-Anforderungen (mit abschluss status STATUS_CANCELLED) aus, die dem abgebrochenen Vorgang zugeordnet sind:
Nicht zugestellte E/A-Anforderungen, die das Framework in der Standard-E/A-Warteschlange des Treibers platziert hat.
Nicht zugestellte E/A-Anforderungen, die das Framework an eine andere Warteschlange weitergeleitet hat, weil der Treiber WdfDeviceConfigureRequestDispatching genannt hat.
Da das Framework diese Anforderungen abbricht, werden sie nicht an den Treiber übermittelt.
Nachdem das Framework eine E/A-Anforderung an den Treiber übermittelt hat, besitzt der Treiber die Anforderung, und das Framework kann sie nicht abbrechen. An diesem Punkt kann nur der Treiber die E/A-Anforderung abbrechen, aber das Framework muss den Treiber benachrichtigen, dass eine Anforderung abgebrochen werden soll. Treiber erhalten diese Benachrichtigung, indem sie eine EvtRequestCancel-Rückruffunktion bereitstellen.
Manchmal empfängt ein Treiber eine E/A-Anforderung von einer E/A-Warteschlange, aber anstatt die Anforderung zu verarbeiten, stellt der Treiber die Anforderung zur späteren Verarbeitung an die gleiche oder eine andere E/A-Warteschlange zurück. Beispiele für diese Situation sind:
Das Framework übermittelt eine E/A-Anforderung an einen der Anforderungshandler des Treibers, und der Treiber ruft anschließend entweder WdfRequestForwardToIoQueue (oder WdfRequestForwardToParentDeviceIoQueue) auf, um die Anforderung in einer anderen Warteschlange zu platzieren, oder WdfRequestRequeue , um die Anforderung wieder in derselben Warteschlange zu platzieren.
Das Framework übermittelt eine E/A-Anforderung an die EvtIoInCallerContext-Rückruffunktion des Treibers, der Treiber ruft WdfDeviceEnqueueRequest auf, um die Anforderung zurück an das Framework zu übergeben, und das Framework platziert die Anforderung anschließend in einer der E/A-Warteschlangen des Treibers.
In diesen Fällen kann das Framework die E/A-Anforderung abbrechen, da sich die Anforderung in einer E/A-Warteschlange befindet. Wenn der Treiber jedoch eine EvtIoCanceledOnQueue-Rückruffunktion für die E/A-Warteschlange registriert hat, in der sich die Anforderung befindet, ruft das Framework die Rückruffunktion auf, anstatt die Anforderung abzubrechen, wenn der zugeordnete E/A-Vorgang abgebrochen wird. Wenn das Framework die Rückruffunktion EvtIoCanceledOnQueue des Treibers aufruft, muss der Treiber die Anforderung abschließen .
Zusammenfassung: Wenn ein E/A-Vorgang abgebrochen wird, bricht das Framework immer alle zugeordneten E/A-Anforderungen ab, die nie an den Treiber übermittelt wurden. Wenn der Treiber eine Anforderung empfängt und dann erneut in die Warteschlange stellt, bricht das Framework die Anforderung ab (wenn sich die Anforderung in der Warteschlange befindet), es sei denn, der Treiber stellt eine EvtIoCanceledOnQueue-Rückruffunktion für die E/A-Warteschlange bereit.
Aufrufen von WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx
Ein Treiber kann WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufrufen, um eine EvtRequestCancel-Rückruffunktion zu registrieren. Wenn der Treiber WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufgerufen hat und der der Anforderung zugeordnete E/A-Vorgang abgebrochen wird, ruft das Framework die Rückruffunktion EvtRequestCancel des Treibers auf, damit der Treiber die E/A-Anforderung abbrechen kann.
Ein Treiber sollte WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufrufen, wenn er eine Anforderung für einen relativ langen Zeitraum besitzt. Beispielsweise muss ein Treiber möglicherweise warten, bis ein Gerät antwortet, oder er kann darauf warten, dass niedrigere Treiber eine Reihe von Anforderungen abschließen, die der Treiber erstellt hat, als er eine einzelne Anforderung empfangen hat.
Wenn ein Treiber WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx nicht aufruft oder wenn ein Treiber WdfRequestUnmarkCancelable nach dem Aufruf von WdfRequestMarkCancelable oder WdfRequestMarkCancelable aufruft, ist dem Treiber der Abbruch nicht bekannt und verarbeitet daher die Anforderung wie gewohnt.
Aufrufen von WdfRequestIsCanceled
Wenn ein Treiber nicht WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufgerufen hat, um eine EvtRequestCancel-Rückruffunktion zu registrieren, kann er WdfRequestIsCanceled aufrufen, um festzustellen, ob der E/A-Manager versucht hat, eine E/A-Anforderung abzubrechen. Wenn WdfRequestIsCanceledTRUE zurückgibt und der Treiber besitzer der Anforderung ist, sollte der Treiber die Anforderung abbrechen. Wenn der Treiber nicht besitzer der Anforderung ist, sollte er WdfRequestIsCanceled nicht aufrufen.
Ein Treiber, der nicht WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufgerufen hat, kann WdfRequestIsCanceled unter den folgenden Umständen aufrufen:
Ein Treiber, der auf Geräteunterbrechungen wartet, kann WdfRequestIsCanceled über seine EvtInterruptDpc-Rückruffunktion aufrufen.
Ein Treiber, der sein Gerät abruft, kann WdfRequestIsCanceled über den Abrufthread aufrufen.
Ein Treiber, der eine DMA-Transaktion in mehrere kleinere Übertragungen unterbricht, kann WdfRequestIsCanceled aufrufen, nachdem jede Übertragung abgeschlossen ist.
Ein Treiber, der eine große Lese- oder Schreibanforderung empfängt, die in mehrere kleinere Anforderungen unterteilt wird, kann WdfRequestIsCanceled aufrufen, nachdem das E/A-Ziel des Treibers jede der kleineren Anforderungen abgeschlossen hat, wenn der Treiber für die empfangene Anforderung nicht WdfRequestMarkCancelable oder WdfRequestMarkCancelableEx aufgerufen hat.
Abbrechen der Anforderung
Das Abbrechen einer E/A-Anforderung kann folgendes umfassen:
Beenden eines laufenden E/A-Vorgangs.
Die Anforderung wird nicht an ein E/A-Ziel weitergeleitet.
Aufrufen von WdfRequestCancelSentRequest , um zu versuchen, eine Anforderung abzubrechen, die der Treiber zuvor an ein E/A-Ziel gesendet hatte.
Wenn ein Treiber eine E/A-Anforderung für ein Anforderungsobjekt abbricht, das der Treiber vom Framework empfangen hat, muss der Treiber die Anforderung immer abschließen, indem er WdfRequestComplete,WdfRequestCompleteWithInformation oder WdfRequestCompleteWithPriorityBoost mit dem Status-Parameter STATUS_CANCELLED aufruft. (Wenn der Treiber WdfRequestCreate aufgerufen hat, um ein Anforderungsobjekt zu erstellen, ruft der Treiber WdfObjectDelete auf, anstatt die Anforderung abzuschließen.)
Synchronisieren des Abbruchs
Informationen zum Synchronisieren von Code, der E/A-Anforderungen abbricht, finden Sie unter: