Verwenden von weder gepufferten noch direkten E/A-Vorgängen

Wenn ein Treiber weder gepufferte noch direkte E/A verwendet, übergibt der E/A-Manager die ursprünglichen virtuellen Benutzerraumadressen in IRPs, die er an den Treiber sendet. Um sicher auf diese Puffer zuzugreifen, muss der Treiber im Kontext des aufrufenden Threads ausgeführt werden. In der Regel können daher nur treiber der höchsten Ebene, z. B. FSDs, diese Methode für den Zugriff auf Puffer verwenden.

Ein Treiber auf mittlerer oder niedrigster Ebene kann diese Bedingung nicht immer erfüllen. Wenn ein anfordernde Thread beispielsweise auf den Abschluss einer E/A-Anforderung wartet oder wenn ein Treiber auf höherer Ebene über dem Treiber der mittleren oder niedrigsten Ebene liegt, ist es unwahrscheinlich, dass die Routinen des Treibers auf niedriger ebener Ebene im Kontext des anfordernden Threads aufgerufen werden.

Der E/A-Manager stellt wie folgt fest, dass ein E/A-Vorgang weder gepuffert noch direkte E/A verwendet:

Wenn ein Treiber eine IRP empfängt, die einen E/A-Vorgang mit weder gepufferten noch direkten E/A-Vorgängen angibt, muss er folgendes tun:

  1. Überprüfen Sie mithilfe der Supportroutinen ProbeForRead und ProbeForWrite die Gültigkeit des Adressbereichs des Benutzerpuffers, und überprüfen Sie, ob der entsprechende Lese- oder Schreibzugriff zulässig ist. Der Treiber muss seine Zugriffe auf den Adressbereich des Puffers in einen vom Treiber bereitgestellten Ausnahmehandler einschließen, damit ein Benutzerthread die Zugriffsrechte für den Puffer nicht ändern kann, während der Treiber auf Arbeitsspeicher zugreift. Wenn der Test eine Ausnahme auslöst, sollte der Treiber einen Fehler zurückgeben. Der Treiber muss diese Routinen im Kontext des Threads aufrufen, der die E/A-Anforderung gestellt hat. Daher kann diese Aufgabe nur von einem Treiber auf höherer Ebene ausgeführt werden.

  2. Verwalten Sie Puffer und Arbeitsspeichervorgänge auf eine der folgenden Arten:

    • Führen Sie eigene Doppelpuffervorgänge aus, wie es der E/A-Manager für Treiber tut, die gepufferte E/A-Vorgänge verwenden. Weitere Informationen finden Sie unter Verwenden von gepufferten E/A-Vorgängen.
    • Erstellen Sie eigene MDLs, und sperren Sie den Puffer, indem Sie die Supportroutinen des Speicher-Managers aufrufen, wie es der E/A-Manager für Treiber tut, die direkte E/A verwenden. Weitere Informationen finden Sie unter Verwenden von direkten E/A-Vorgängen.
    • Führen Sie alle erforderlichen Vorgänge für den Benutzerpuffer direkt im Kontext des aufrufenden Threads aus. Der Treiber muss seinen Zugriff auf den Puffer in einem vom Treiber bereitgestellten Ausnahmehandler umschließen, falls ein Benutzerthread entweder die Zugriffsrechte für den Puffer oder die Daten im Puffer ändert, während der Treiber auf Arbeitsspeicher zugreift. Weitere Informationen finden Sie unter Behandeln von Ausnahmen.

Tatsächlich muss der Treiber pro IRP auswählen, ob gepufferte E/A, direkte E/A oder E/A im Kontext des aufrufenden Threads ausgeführt werden soll, und er muss alle Ausnahmen behandeln, die in einem Threadkontext im Benutzermodus auftreten können. Der Treiber muss bei Bedarf eigene Benutzerpufferzugriffe, Doppelpuffervorgänge und Speicherzuordnungen verwalten, anstatt diese Vorgänge für den Treiber vom E/A-Manager verarbeiten zu lassen.