Releasequeue-Routine des Speicherklassentreibers
Sofern ein Speicherklassentreiber die SrbFlags für eine bestimmte Anforderung mit SRB_FLAGS_NO_QUEUE_FREEZE nicht übergibt, friert der Systemporttreiber eine Warteschlange für eine bestimmte logische Einheit nach einer der folgenden Aktionen ein:
Beim Ausführen einer Anforderung durch die logische Einheit wurde eine Busrücksetzung durchgeführt.
Die logische Einheit hat SCSISTAT_CHECK_CONDITION oder SCSISTAT_COMMAND_TERMINATED zurückgegeben, die der Klassentreiber im ScsiStatus-Member des SRB finden kann.
Für eine Anforderung wurde ein Timeout ausgeführt.
Eine Anforderung wurde durch einen Busmeldungsbefehl wie SCSIMESS_ABORT beendet.
Der Porttreiber gibt an, dass eine LU-spezifische Warteschlange eingefroren wurde, indem eine Anforderung mit SRB_STATUS_QUEUE_FROZEN im SrbStatus-Member zurückgegeben wird. Neue Anforderungen vom Klassentreiber können in die Warteschlange eingefügt werden, aber nur AutoSense-Anforderungen werden an die logische Einheit gesendet, solange die Warteschlange eingefroren ist.
Das Einfrieren der Warteschlange unter diesen Bedingungen gibt jedem Speicherklassentreiber die Möglichkeit, einen Fehler zu analysieren, bevor andere Aufträge in der Warteschlange ausgeführt werden. Beispielsweise müssen Aufträge in der Warteschlange abgebrochen werden, wenn sich die Medien geändert haben. Um die Warteschlange zu leeren, kann der Treiber eine Anforderung mit dem SrbFlags ORed mit SRB_FLAGS_BYPASS_FROZEN_QUEUE senden.
Eine ReleaseQueue-Routine ordnet ein IRP und einen SRB zu und richtet diese ein, um eine eingefrorene Warteschlange entweder zu freigeben oder zu leeren. Der Funktionsmember des SRB muss auf SRB_FUNCTION_RELEASE_QUEUE oder SRB_FUNCTION_FLUSH_QUEUE festgelegt werden, wodurch sowohl eine eingefrorene Warteschlange freigegeben wird als auch alle derzeit in die Warteschlange gestellten Anforderungen für die logische Zieleinheit abgebrochen werden. Der Porttreiber schließt alle Anforderungen in einer geleerten Warteschlange ab, wobei seine SrbStatus-Member auf SRB_STATUS_REQUEST_FLUSHED festgelegt sind.
Wenn eine eingefrorene Warteschlange nicht freigegeben wird, kann auf das Gerät nicht zugegriffen werden, sodass die ReleaseQueue-Routine eines Treibers so konzipiert sein sollte, dass sie auch bei niedrigen Speicherbedingungen erfolgreich ist. Eine ReleaseQueue-Routine sollte zuerst versuchen, Arbeitsspeicher für einen SRB zuzuweisen, indem ExAllocatePool mit dem Speichertyp NonPagedPool aufgerufen wird. Wenn diese Zuordnung fehlschlägt, verwenden Sie einen SRB, der während der Treiberinitialisierung vorab zugewiesen wurde. Wenn der Treiber einen SRB zuweist, der bei der Initialisierung seiner Geräteerweiterung in reserve gehalten werden soll, wie unter Einrichten der Geräteerweiterung eines Speicherklassentreibers beschrieben, kann seine ReleaseQueue diesen SRB verwenden, wenn der Arbeitsspeicherpool niedrig ist, mit einem entsprechenden Synchronisierungsmechanismus, falls mehrere gleichzeitige Releasevorgänge erforderlich sind.
Beachten Sie, dass die ReleaseQueue-Routine eines Klassentreibers asynchron aufgerufen wird, im Allgemeinen aus der IoCompletion-Routine . Die IoCompletion-Routine eines Klassentreibers kann ReleaseQueue nicht aufrufen, um eine Warteschlange zu leeren, die nicht eingefroren ist. Es kann jedoch ReleaseQueue aufrufen, um eine nicht infrozen Warteschlange zu lösen, und der Porttreiber ignoriert eine solche Anforderung einfach.