Freigeben über


Zugreifen auf Freigegebene Zustandsinformationen

Verwenden Sie die folgenden allgemeinen Richtlinien zum Entwerfen und Schreiben von SynchCritSection-Routinen , die den Zustand beibehalten:

  • Um auf Daten zuzugreifen, auf die auch ein ISR zugreift, muss eine Treiberroutine eine SynchCritSection-Routine aufrufen. Nicht kritischer Abschnittscode kann unterbrochen werden. Denken Sie daran, dass es nicht ausreicht, einfach eine Spin-Sperre zu erwerben, um Daten zu schützen, auf die auch ISRs zugreifen, da ISRs bei DIRQL ausgeführt werden und das Abrufen einer Drehsperre (KeAcquireSpinLock) IRQL nur auf DISPATCH_LEVEL erhöht, wodurch ein Interrupt den ISR auf dem aktuellen Prozessor aufrufen kann.

  • Weisen Sie jeder SynchCritSection-Routine, die Zustandsinformationen verwaltet, die Verantwortung für einen diskreten Satz von Zustandsvariablen zu. Das heißt, vermeiden Sie das Schreiben von SynchCritSection-Routinen , die sich überlappende Zustandsinformationen beibehalten.

    Dies verhindert Konflikte und möglicherweise Racebedingungen zwischen SynchCritSection-Routinen (und der ISR), die versuchen, gleichzeitig auf denselben Zustand zuzugreifen.

    Dadurch wird auch sichergestellt, dass jede SynchCritSection-Routine die Steuerung so schnell wie möglich zurückgibt, da eine SynchCritSection-Routine nie auf eine andere warten muss, die einige der gleichen Zustandsinformationen aktualisiert, um die Steuerung zurückzugeben.

  • Vermeiden Sie es, eine einzelne, große, universelle SynchCritSection-Routine zu schreiben, die mehr Tests von Bedingungen durchführt, um zu bestimmen, was zu tun ist, als tatsächlich nützliche Arbeit zu erledigen. Auf der anderen Seite sollten Sie viele SynchCritSection-Routinen vermeiden, die nie eine bedingte Anweisung ausführen, da jede nur ein einzelnes Byte von Zustandsinformationen aktualisiert.

  • Jede SynchCritSection-Routine muss die Steuerung so schnell wie möglich zurückgeben, da das Ausführen einer SynchCritSection-Routine verhindert, dass die ISR des Treibers ausgeführt wird.

Im Folgenden finden Sie eine Technik zum Verwalten eines Zeitgeberzählers in einer Geräteerweiterung. Angenommen, der Treiber verwendet den Zähler, um zu bestimmen, ob ein E/A-Vorgang ein Timeout aufweist. Angenommen, der Treiber überschneidet sich nicht mit E/A-Vorgängen.

  • Die StartIo-Routine des Treibers initialisiert den Zeitgeberzähler auf einen Anfangswert für jede E/A-Anforderung. Der Treiber fügt dann dem Wert für das Gerätetimeout eine Sekunde hinzu, falls seine IoTimer-Routine gerade die Steuerung zurückgegeben hat.

  • Die ISR des Treibers muss diesen Timerzähler auf minus 1 festlegen.

  • Die IoTimer-Routine des Treibers wird einmal pro Sekunde aufgerufen, um den Zeitzähler zu lesen und zu bestimmen, ob der ISR ihn bereits auf minus 1 festgelegt hat. Andernfalls dekrementiert die IoTimer-Routine den Zähler mithilfe von KeSynchronizeExecution , um eine SynchCritSection_1 Routine aufzurufen.

    Wenn der Zähler auf 0 (null) zurückgeht und angibt, dass für die Anforderung ein Timeout aufgetreten ist, ruft die SynchCritSection_1 Routine eine SynchCritSection_2 Routine auf, um einen Vorgang zum Zurücksetzen des Geräts zu programmieren. Wenn der Zähler minus 1 ist, wird die IoTimer-Routine einfach zurückgegeben.

  • Wenn die DpcForIsr-Routine des Treibers das Gerät umprogrammieren muss, um einen Teilübertragungsvorgang zu starten, muss der Zeitgeberzähler wie die StartIo-Routine neu initialisiert werden.

    Die DpcForIsr-Routine muss auch KeSynchronizeExecution verwenden, um die SynchCritSection_2-Routine oder möglicherweise eine SynchCritSection_3 Routine aufzurufen, um das Gerät für einen anderen Übertragungsvorgang zu programmieren.

In diesem Szenario verfügt der Treiber über mehr als eine SynchCritSection-Routine mit jeweils diskreten, spezifischen Zuständigkeiten. eine, die ihren Timerzähler verwaltet, und eine oder mehrere andere zum Programmieren des Geräts. Jede SynchCritSection-Routine kann die Steuerung schnell zurückgeben, da sie eine einzelne, diskrete Aufgabe ausführt.

Beachten Sie, dass der Treiber über eine einzelne SynchCritSection_1 Routine verfügt, die zusammen mit der ISR des Treibers den Zustand für den Zeitgeberzähler beibehält. Daher gibt es keinen Konflikt um den Zugriff auf den Zeitgeberzähler zwischen mehreren SynchCritSection-Routinen und der ISR.