Freigeben über


Multiprocessor-Safe

Das auf Microsoft Windows NT basierende Betriebssystem ist für die einheitliche Ausführung auf Uniprozessor- und symmetrischen Multiprozessorplattformen (SMP)-Plattformen konzipiert, und Kernelmodustreiber sollten entsprechend konzipiert sein.

In jeder Windows-Multiprozessorplattform sind die folgenden Bedingungen vorhanden:

  • Alle CPUs sind identisch, und entweder alle oder keine der Prozessoren müssen identische Koprozessoren haben.

  • Alle CPUs teilen Arbeitsspeicher und haben einen einheitlichen Zugriff auf den Arbeitsspeicher.

  • In einer symmetrischen Plattform kann jede CPU auf Arbeitsspeicher zugreifen, eine Unterbrechung nehmen und auf E/A-Steuerungsregister zugreifen. (Im Gegensatz dazu nimmt eine CPU in einem asymmetrischen Multiprozessorcomputer alle Unterbrechungen für eine Reihe untergeordneter CPUs an.)

Um sicher auf einer SMP-Plattform ausgeführt zu werden, muss ein Betriebssystem garantieren, dass Code, der auf einem Prozessor ausgeführt wird, nicht gleichzeitig auf Daten zugreift und ändert, auf die ein anderer Prozessor zugreift und ändert. Wenn z. B. der ISR eines Treibers auf der niedrigsten Ebene einen Geräteunterbruch auf einem Prozessor verarbeitet, muss er exklusiven Zugriff auf Geräteregister oder kritische, treiberdefinierte Daten haben, falls das Gerät gleichzeitig auf einem anderen Prozessor unterbricht.

Darüber hinaus können die I/O-Vorgänge, die in einem Einprozessorsystem serialisiert werden, in einem SMP-Computer überlappen. Das heißt, eine Treiberroutine, die eingehende E/A-Anforderungen verarbeitet, kann auf einem Prozessor ausgeführt werden, während eine andere Routine, die mit dem Gerät kommuniziert, gleichzeitig auf einem anderen Prozessor ausgeführt wird. Unabhängig davon, ob Kernelmodustreiber auf einem Uniprozessor- oder symmetrischen Multiprozessorcomputer ausgeführt werden, müssen sie den Zugriff auf alle treiberdefinierte Daten oder vom System bereitgestellte Ressourcen synchronisieren, die von Treiberroutinen gemeinsam genutzt werden, und den Zugriff auf das physische Gerät synchronisieren, falls vorhanden.

Die Windows NT-Kernelkomponente exportiert einen Synchronisierungsmechanismus, der als Spin lock bezeichnet wird, mit dem Treiber freigegebene Daten (oder Geräteregister) vor gleichzeitigem Zugriff durch eine oder mehrere Routinen schützen können, die gleichzeitig auf einer symmetrischen Multiprozessorplattform ausgeführt werden. Der Kernel erzwingt zwei Richtlinien für die Verwendung von Spin-Sperren:

  • Nur eine Routine kann zu einem bestimmten Zeitpunkt einen bestimmten Spinlock halten. Vor dem Zugriff auf freigegebene Daten muss jede Routine, die auf die Daten zugreifen muss, zuerst versuchen, den Spinlock der Daten zu erwerben. Um auf dieselben Daten zuzugreifen, muss eine andere Routine den Spinlock erwerben, aber der Spinlock kann erst genommen werden, wenn der aktuelle Inhaber ihn freigibt.

  • Der Kernel weist jedem Spin-Lock im System einen IRQL-Wert zu. Eine Routine im Kernelmodus kann einen bestimmten Spinlock nur erwerben, wenn die Routine auf dem dem Spinlock zugewiesenen IRQL ausgeführt wird.

Diese Richtlinien verhindern, dass eine Treiberroutine, die normalerweise auf einem niedrigeren IRQL läuft und derzeit ein Spinlock hält, durch eine höher priorisierte Treiberroutine unterbrochen wird, die versucht, denselben Spinlock zu erwerben. So wird ein Deadlock vermieden.

Die IRQL, die einem Spin-Lock zugewiesen ist, entspricht in der Regel der höchsten IRQL derjenigen Routine, die den Spin-Lock erwerben kann.

Beispielsweise teilt ein ISR auf der niedrigsten Ebene häufig einen Zustandsbereich mit der DPC-Routine des Fahrers. Die DPC-Routine ruft eine vom Treiber bereitgestellte Routine für einen kritischen Abschnitt auf, um auf den freigegebenen Bereich zuzugreifen. Die Spinlock, die den freigegebenen Bereich schützt, weist einen IRQL-Wert auf, der dem DIRQL entspricht, auf dem das Gerät unterbricht. Solange die Routine des kritischen Abschnitts den Spinlock hält und auf den freigegebenen Bereich bei DIRQL zugreift, kann der ISR weder auf einem Uniprozessor noch auf einem SMP-Computer ausgeführt werden.

  • Der ISR kann nicht auf einem Uniprozessorcomputer ausgeführt werden, da der Geräteunterbruch maskiert ist, wie in Always Preemptible und Always Interruptible beschrieben.

  • Auf einem SMP-Computer kann der ISR die Drehungssperre nicht abrufen, die die freigegebenen Daten schützt, während die Kritische Abschnittsroutine die Drehungssperre enthält und auf die freigegebenen Daten bei DIRQL zugreift.

Ein Satz von Threads im Kernel-Modus kann den Zugriff auf freigegebene Daten oder Ressourcen synchronisieren, indem auf eines der Dispatcherobjekte des Kernels gewartet wird: ein Ereignis, ein Mutex, ein Semaphor, ein Timer oder ein anderer Thread. Die meisten Treiber richten jedoch keine eigenen Threads ein, da sie eine bessere Leistung haben, wenn sie Threadkontextoptionen vermeiden. Immer wenn zeitkritische Kernelmodus-Routinen und Treiber bei IRQL = DISPATCH_LEVEL oder bei DIRQL ausgeführt werden, müssen sie die Spin-Sperren des Kernels verwenden, um den Zugriff auf gemeinsam genutzte Daten oder Ressourcen zu synchronisieren.

Weitere Informationen finden Sie unter Spin Locks, Managing Hardware Priorities, and Kernel Dispatcher Objects.