Freigeben über


Beispiel-E/A-Anforderung : Die Details

Die Abbildung zum Öffnen eines Dateiobjekts zeigt eine IRP mit zwei E/A-Stapelspeicherorten, aber ein IRP kann eine beliebige Anzahl von E/A-Stapelspeicherorten aufweisen, je nachdem, wie viele mehrschichtige Treiber eine bestimmte Anforderung verarbeiten.

Die folgende Abbildung veranschaulicht ausführlicher, wie die Treiber in der Abbildung Öffnen eines Dateiobjekts E/A-Unterstützungsroutinen (IoXxx-Routinen ) verwenden, um die IRP für eine Lese- oder Schreibanforderung zu verarbeiten.

Diagramm, das die Verarbeitung von Irps in mehrstufigen Treibern veranschaulicht.

  1. Der E/A-Manager ruft den Dateisystemtreiber (FSD) mit dem IRP auf, den er für die Lese-/Schreibanforderung des Subsystems zugewiesen hat. Der FSD greift auf seinen E/A-Stapelspeicherort im IRP zu, um zu bestimmen, welcher Vorgang ausgeführt werden soll.

  2. Der FSD kann die ursprüngliche Anforderung in kleinere Anforderungen (möglicherweise für mehrere Gerätetreiber) unterteilen, indem eine E/A-Supportroutine (IoAllocateIrp) mehrmals aufgerufen wird, um zusätzliche IRPs zuzuweisen. Die zusätzlichen IRPs werden an die FSD mit nullgefüllten E/A-Stapelspeicherorten für Treiber niedrigerer Ebene zurückgegeben. Nach eigenem Ermessen kann der FSD den ursprünglichen IRP wiederverwenden, anstatt zusätzliche IRPs zuzuweisen, wie in der vorherigen Abbildung gezeigt, indem der E/A-Stapelspeicherort des nächstniedrigen Treibers im ursprünglichen IRP eingerichtet und an niedrigere Treiber übergeben wird.

  3. Für jede vom Treiber zugewiesene IRP ruft der FSD in der vorherigen Abbildung eine E/A-Unterstützungsroutine auf, um eine von FSD bereitgestellte Vervollständigungsroutine zu registrieren. in der Vervollständigungsroutine kann der FSD bestimmen, ob niedrigere Treiber die Anforderung erfüllt haben, und kann jeden treiberseitig zugewiesenen IRP freigeben, wenn niedrigere Treiber sie abgeschlossen haben. Der E/A-Manager ruft die von FSD bereitgestellte Vervollständigungsroutine auf, unabhängig davon, ob jede vom Treiber zugewiesene IRP erfolgreich abgeschlossen, mit einem Fehler status abgeschlossen oder abgebrochen wurde. Ein Treiber auf höherer Ebene ist dafür verantwortlich, alle IRPs freizugeben, die er ordnet und im eigenen Namen für Treiber auf niedrigerer Ebene einrichtet. Der E/A-Manager gibt die IRPs frei, die er ordnet, nachdem sie von allen Treibern abgeschlossen wurden.

    Als Nächstes ruft der FSD eine E/A-Unterstützungsroutine (IoGetNextIrpStackLocation) auf, um auf den E/A-Stapelspeicherort des nächstniedrigen Treibers zuzugreifen, um die Anforderung für den nächstniedrigen Treiber einzurichten. (In der vorherigen Abbildung ist der nächstniedrige Treiber der niedrigste Treiber.) Der FSD ruft dann eine E/A-Supportroutine (IoCallDriver) auf, um diese IRP an den nächstniedrigen Treiber zu übergeben.

  4. Wenn er mit dem IRP aufgerufen wird, überprüft der Treiber der niedrigsten Ebene seinen E/A-Stapelspeicherort, um zu bestimmen, welchen Vorgang (durch den IRP_MJ_XXX-Funktionscode ) er auf dem Zielgerät ausführen soll. Das Zielgerät wird durch das Geräteobjekt an seinem angegebenen E/A-Stapelspeicherort dargestellt und mit dem IRP an den Treiber übergeben. Der Treiber der niedrigsten Ebene kann davon ausgehen, dass der E/A-Manager den IRP an einen Einstiegspunkt weitergeleitet hat, den der Treiber für den IRP_MJ_XXX-Vorgang definiert hat (hier IRP_MJ_READ oder IRP_MJ_WRITE), und dass der Treiber der höheren Ebene die Gültigkeit anderer Parameter für die Anforderung überprüft hat.

    Wenn kein Treiber auf höherer Ebene vorhanden ist, überprüft der Treiber der niedrigsten Ebene, ob die Eingabeparameter für einen IRP_MJ_XXX-Vorgang gültig sind. Wenn dies der Grund ist, ruft der Treiber in der Regel E/A-Supportroutinen auf, um den E/A-Manager zu informieren, dass ein Gerätevorgang auf dem IRP aussteht, und um die IRP entweder in die Warteschlange zu stellen oder ihn an eine andere vom Treiber bereitgestellte Routine zu übergeben, die auf das Zielgerät zugreift (hier ein physisches oder logisches Gerät: den Datenträger oder eine Partition auf dem Datenträger).

  5. Der E/A-Manager ermittelt, ob der Treiber bereits mit der Verarbeitung eines anderen IRP für das Zielgerät beschäftigt ist, stellt die IRP in die Warteschlange, falls vorhanden, und gibt zurück. Andernfalls leitet der E/A-Manager den IRP an eine vom Treiber bereitgestellte Routine weiter, die den E/A-Vorgang auf dem Gerät startet. (In dieser Phase geben beide Treiber in der vorherigen Abbildung und der E/A-Manager die Steuerung zurück.)

  6. Wenn das Gerät unterbricht, leistet die Interrupt-Dienstroutine (ISR) des Treibers nur so viel Arbeit, wie es erforderlich ist, um das Gerät an der Unterbrechung zu hindern und den erforderlichen Kontext für den Vorgang zu speichern. Der ISR ruft dann eine E/A-Supportroutine (IoRequestDpc) mit dem IRP auf, um eine vom Treiber bereitgestellte DPC-Routine (Deferred Procedure Call) in die Warteschlange zu stellen, um den angeforderten Vorgang mit einer niedrigeren Hardwarepriorität als die ISR abzuschließen.

  7. Wenn der DPC des Treibers die Kontrolle erhält, verwendet er den Kontext (der im Aufruf des ISR an IoRequestDpc übergeben wird), um den E/A-Vorgang abzuschließen. Der DPC ruft eine Supportroutine auf, um die nächste IRP (falls vorhanden) zu löschen und diese IRP an die vom Treiber bereitgestellte Routine zu übergeben, die E/A-Vorgänge auf dem Gerät startet (siehe Schritt 5). Der DPC legt dann status über den gerade abgeschlossenen Vorgang im I/O-status-Block des IRP fest und gibt ihn mit IoCompleteRequest an den E/A-Manager zurück.

  8. Der E/A-Manager nullt den E/A-Stapelspeicherort des Treibers auf niedrigster Ebene im IRP und ruft die registrierte Vervollständigungsroutine des Dateisystems (siehe Schritt 3) mit dem FSD-zugewiesenen IRP auf. Diese Vervollständigungsroutine überprüft den E/A-status-Block, um zu ermitteln, ob die Anforderung erneut ausgeführt oder ein interner Zustand aktualisiert werden soll, der über die ursprüngliche Anforderung beibehalten wird, und um die vom Treiber zugewiesene IRP freizusetzen. Das Dateisystem kann status Informationen für alle treiberseitig zugewiesenen IRPs sammeln, die es an Treiber auf niedrigerer Ebene sendet, sodass es E/A-status festlegen und die ursprüngliche IRP abschließen kann. Wenn das Dateisystem den ursprünglichen IRP abgeschlossen hat, gibt der E/A-Manager den Wert ntstatus an den ursprünglichen Anforderer (die native Funktion des Subsystems) des E/A-Vorgangs zurück.

Wie der Dateisystemtreiber in der Abbildung Verarbeitung von IRPs in Mehrschichttreibern kann jeder neue Treiber, der einer Kette vorhandener Treiber hinzugefügt wird, folgendes ausführen:

  • Legen Sie eine eigene Vervollständigungsroutine in eine IRP fest. Die IoCompletion-Routine überprüft den E/A-status-Block, um festzustellen, ob niedrigere Treiber die IRP erfolgreich abgeschlossen, die IRP abgebrochen und/oder mit einem Fehler abgeschlossen haben. Die Vervollständigungsroutine kann auch jeden IRP-spezifischen Zustand aktualisieren, den der Treiber möglicherweise gespeichert hat, alle vorgangsspezifischen Ressourcen freigeben, die der Treiber möglicherweise zugewiesen hat, bevor die IRP abgeschlossen wird. Darüber hinaus kann die Vervollständigungsroutine die IRP-Vervollständigung verschieben (indem sie den E/A-Manager darüber informiert, dass mehr Verarbeitung auf dem IRP erforderlich ist), und eine weitere Anforderung an den nächstniedrigen Treiber senden, bevor die IRP abgeschlossen werden kann.

  • Richten Sie den E/A-Stapelspeicherort des Treibers der nächstniedrigen Ebene in den IRPs ein, die er ordnet, und senden Sie Anforderungen an den Treiber der nächstniedrigen Ebene.

  • Übergeben Sie alle eingehenden Anforderungen an niedrigere Treiber, indem Sie den E/A-Stapelspeicherort des nächstniedrigen Treibers in jedem IRP einrichten und IoCallDriver aufrufen. (Beachten Sie, dass Treiber für IRPs mit Hauptfunktionscode IRP_MJ_POWERPoCallDriver verwenden müssen.)

Jedes vom Treiber erstellte Geräteobjekt stellt ein physisches, logisches oder virtuelles Gerät dar, für das ein bestimmter Treiber E/A-Anforderungen ausführt. Ausführliche Informationen zum Erstellen und Einrichten eines Geräteobjekts finden Sie unter Geräteobjekte und Gerätestapel.

Wie auch die Abbildung Verarbeitungs-IRPs in Mehrschichttreibern zeigt, verarbeiten die meisten Treiber jede IRP in Phasen über einen vom Treiber bereitgestellten Satz systemdefinierter Standardroutinen, aber Treiber auf verschiedenen Ebenen in einer Kette verfügen notwendigerweise über unterschiedliche Standardroutinen. Beispielsweise verarbeiten nur Treiber der niedrigsten Ebene Interrupts von einem physischen Gerät, sodass nur ein Treiber der niedrigsten Ebene über einen ISR und einen DPC verfügt, der unterbrechungsgesteuerte E/A-Vorgänge abschließt. Da ein solcher Treiber andererseits weiß, dass die E/A-Vorgänge abgeschlossen sind, wenn er einen Interrupt von seinem Gerät empfängt, ist keine Abschlussroutine erforderlich. Nur ein Treiber auf höherer Ebene verfügt über eine oder mehrere Abschlussroutinen wie die FSD in dieser Abbildung.