E/A-Stapelspeicherorte
Der E/A-Manager gibt jedem Treiber in einer Kette von mehrstufigen Treibern einen E/A-Stapelspeicherort für jeden IRP, den er eingerichtet hat. Jede E/A-Stapelposition besteht aus einer IO_STACK_LOCATION-Struktur .
Der E/A-Manager erstellt ein Array von E/A-Stapelspeicherorten für jede IRP mit einem Arrayelement, das jedem Treiber in einer Kette von mehrstufigen Treibern entspricht. Jeder Treiber besitzt einen der Stapelspeicherorte im Paket und ruft IoGetCurrentIrpStackLocation auf, um treiberspezifische Informationen zum E/A-Vorgang abzurufen.
Jeder Treiber in einer solchen Kette ist dafür verantwortlich, IoGetNextIrpStackLocation aufzurufen und dann den E/A-Stapelspeicherort des nächstniedrigen Treibers einzurichten. Der E/A-Stapelspeicherort eines beliebigen übergeordneten Treibers kann auch verwendet werden, um den Kontext zu einem Vorgang zu speichern, sodass die IoCompletion-Routine des Treibers ihre Bereinigungsvorgänge ausführen kann.
Die Abbildung Verarbeitungs-IRPs in Mehrschichttreibern zeigt zwei E/A-Stapelspeicherorte im ursprünglichen IRP, da sie zwei Treiber, einen Dateisystemtreiber und einen Massenspeichergerätetreiber zeigt. Die treiberseitig zugewiesenen IRPs in der Abbildung Verarbeitungs-IRPs in Mehrschichttreibern verfügen nicht über einen Stapelspeicherort für den FSD (Dateisystemtreiber), von dem sie erstellt wurden. Jeder Treiber auf höherer Ebene, der IRPs für Treiber auf niedrigerer Ebene ordnet, bestimmt auch, wie viele E/A-Stapelspeicherorte die neuen IRPs gemäß dem StackSize-Wert des Geräteobjekts des nächstniedrigen Treibers aufweisen sollten.
Die folgende Abbildung zeigt den Inhalt der IRP ausführlicher.
Wie in der Abbildung dargestellt, enthält jeder treiberspezifische E/A-Stapelspeicherort in einem IRP die folgenden allgemeinen Informationen:
Der Hauptfunktionscode (IRP_MJ_XXX), der den grundlegenden Vorgang angibt, den der Treiber ausführen soll.
Für einige wichtige Funktionscodes, die von FSDs, übergeordneten SCSI-Treibern und allen PnP-Treibern verarbeitet werden, ist ein Nebenfunktionscode (IRP_MN_XXX), der angibt, welche Unterbuchstaben des grundlegenden Vorgangs der Treiber ausführen soll.
Eine Reihe von vorgangsspezifischen Argumenten, z. B. länge und Startort eines Puffers, in den oder von dem der Treiber Daten überträgt
Ein Zeiger auf das vom Treiber erstellte Geräteobjekt, das das (physische, logische oder virtuelle) Zielgerät für den angeforderten Vorgang darstellt.
Ein Zeiger auf das Dateiobjekt, das eine geöffnete Datei, ein Gerät, ein Verzeichnis oder ein Volume darstellt
Ein Dateisystemtreiber greift über seinen E/A-Stapelspeicherort in IRPs auf das Dateiobjekt zu. Andere Treiber ignorieren normalerweise das Dateiobjekt.
Der Satz von IRP-Haupt- und Nebenfunktionscodes, die ein bestimmter Treiber verarbeitet, kann gerätetypspezifisch sein. Treiber der niedrigsten Ebene und Zwischentreiber (einschließlich PnP-Funktion und Filtertreiber) verarbeiten jedoch in der Regel die folgenden Grundlegenden Anforderungen:
IRP_MJ_CREATE : Öffnen Sie das Zielgerätobjekt, um anzugeben, dass es vorhanden und für E/A-Vorgänge verfügbar ist.
IRP_MJ_READ – Daten vom Gerät übertragen
IRP_MJ_WRITE – Daten auf das Gerät übertragen
IRP_MJ_DEVICE_CONTROL – Einrichten (oder Zurücksetzen) des Geräts gemäß einem systemdefinierten, gerätetypspezifischen E/A-Steuerungscode (IOCTL)
IRP_MJ_CLOSE – Schließen des Zielgeräteobjekts
IRP_MJ_PNP : Führen Sie einen Plug & Play Vorgang auf dem Gerät aus. Eine IRP_MJ_PNP Anforderung wird vom PnP-Manager über den E/A-Manager gesendet.
IRP_MJ_POWER – Führen Sie einen Netzvorgang auf dem Gerät aus. Eine IRP_MJ_POWER Anforderung wird vom Power Manager über den E/A-Manager gesendet.
Weitere Informationen zu den wichtigsten IRP-Funktionscodes, die Treiber verarbeiten müssen, finden Sie unter IRP-Hauptfunktionscodes.
Im Allgemeinen sendet der E/A-Manager IRPs mit mindestens zwei E/A-Stapelspeicherstandorten an Massenspeichergerätetreiber, da ein Dateisystem über andere Treiber für Massenspeichergeräte verteilt ist. Der E/A-Manager sendet IRPs mit einem einzelnen Stapelspeicherort an jeden Treiber, für den kein anderer Treiber darüber liegt.
Der E/A-Manager bietet jedoch Unterstützung für das Hinzufügen eines neuen Treibers zu jeder Kette vorhandener Treiber im System. Beispielsweise kann ein Zwischenspiegeltreiber , der Daten auf einer bestimmten Datenträgerpartition sichert, zwischen einem Treiberpaar eingefügt werden, z. B. dem Dateisystemtreiber und dem Treiber der niedrigsten Ebene, die in der Abbildung Verarbeiten von IRPs in Mehrschichttreibern dargestellt ist. Wenn sich dieser neue Treiber an den Gerätestapel anfügt, passt der E/A-Manager die Anzahl der E/A-Stapelspeicherorte in allen IRPs an, die er an das Dateisystem, die Spiegelung und die Treiber der niedrigsten Ebene sendet. Jedes IRP, das dem Dateisystem in der Abbildung Verarbeitungs-IRPs in Mehrschichttreibern zugeordnet ist, würde auch einen anderen E/A-Stapelspeicherort für einen solchen neuen Spiegeltreiber enthalten.
Beachten Sie, dass diese Unterstützung für das Hinzufügen neuer Treiber zu einer vorhandenen Kette bestimmte Einschränkungen für den Zugriff eines bestimmten Treibers auf die E/A-Stapelspeicherorte in IRPs beinhaltet:
Ein Treiber auf höherer Ebene in einer Kette von mehrstufigen Treibern kann sicher nur auf die E/A-Stapelstandorte des Treibers und die nächstniedrigen Treiber in jedem IRP zugreifen. Ein solcher Treiber muss den E/A-Stapelspeicherort für den nächstniedrigen Treiber in IRPs einrichten. Beim Entwerfen eines solchen Treibers auf höherer Ebene können Sie jedoch nicht vorhersagen, wann (oder ob) ein neuer Treiber zur vorhandenen Kette direkt unter Ihrem Treiber hinzugefügt wird.
Daher sollten Sie davon ausgehen, dass jeder später hinzugefügte Treiber die gleichen IRP-Hauptfunktionscodes (IRP_MJ_XXX) wie der verdrängte Treiber der nächstniedrigen Ebene verarbeitet.
Der Treiber der niedrigsten Ebene in einer Kette von Mehrschichttreibern kann sicher nur auf seinen eigenen E/A-Stapelspeicherort in jedem IRP zugreifen. Beim Entwerfen eines solchen Treibers können Sie nicht vorhersagen, wann (oder ob) der vorhandenen Kette über Ihrem Gerätetreiber ein neuer Treiber hinzugefügt wird.
Gehen Sie beim Entwerfen eines Treibers der niedrigsten Ebene davon aus, dass der Treiber IRPs weiterhin verarbeiten kann, indem die Informationen verwendet werden, die an seinem eigenen E/A-Stapelspeicherort übergeben werden, unabhängig von der Ursprungsquelle eines bestimmten IRP und unabhängig davon, wie viele Treiber darüber liegen.