Freigeben über


Immer präemptiv und immer unterbrechbar

Ziel des vorab zu unterbrechenden Entwurfs des Betriebssystems ist es, die Systemleistung zu maximieren. Jeder Thread kann von einem Thread mit höherer Priorität präemptiv unterbrochen werden, und die Interrupt-Dienstroutine (ISR) eines Treibers kann von einer Routine unterbrochen werden, die auf einer höheren Interruptanforderungsebene (IRQL) ausgeführt wird.

Die Kernelkomponente bestimmt, wann eine Codesequenz ausgeführt wird, je nach einem der folgenden Priorisierungskriterien:

  • Das kerneldefinierte Laufzeitprioritätsschema für Threads.

    Jeder Thread im System verfügt über ein zugeordnetes Prioritätsattribut. Im Allgemeinen weisen die meisten Threads variable Prioritätsattribute auf: Sie sind immer vorerwendbar und sind für die Ausführung von Roundrobin mit allen anderen Threads geplant, die derzeit auf derselben Prioritätsebene sind. Einige Threads verfügen über Echtzeit-Prioritätsattribute: Diese zeitkritischen Threads werden bis zum Abschluss ausgeführt, es sei denn, sie werden von einem Thread mit einem Attribut mit höherer Echtzeitpriorität vorgedrängt. Die Microsoft Windows-Architektur bietet kein systeminternes Echtzeitsystem.

    Unabhängig von seinen Prioritätsattributen kann jeder Thread im System unterbrochen werden, wenn Hardware- und bestimmte Arten von Softwareunterbrechungen auftreten.

  • Die kerneldefinierte Interruptanforderungsebene (IRQL), der ein bestimmter Interruptvektor auf einer bestimmten Plattform zugewiesen wird.

    Der Kernel priorisiert Hardware- und Softwareunterbrechungen, sodass einige Kernelmoduscode, einschließlich der meisten Treiber, bei höheren IRQLs ausgeführt werden, wodurch sie eine höhere Planungspriorität als andere Threads im System haben. Die spezielle IRQL, bei der ein Kernelmodustreibercode ausgeführt wird, wird durch die Hardwarepriorität des zugrunde liegenden Geräts bestimmt.

    Kernelmoduscode ist immer unterbrechungsfähig: Eine Unterbrechung mit einem höheren IRQL-Wert kann jederzeit auftreten, wodurch ein anderer Kernelmoduscode mit einem höheren systembasierten IRQL sofort auf diesem Prozessor ausgeführt wird. Wenn jedoch ein Codeteil bei einem bestimmten IRQL ausgeführt wird, maskiert der Kernel alle Unterbrechungsvektoren mit einem niedrigeren oder gleichen IRQL-Wert auf dem Prozessor.

Die niedrigste IRQL-Ebene wird PASSIVE_LEVEL genannt. Auf dieser Ebene sind keine Unterbrechungsvektoren maskiert. Threads werden in der Regel bei IRQL=PASSIVE_LEVEL ausgeführt. Die nächsten höheren IRQL-Ebenen gelten für Softwareunterbrechungen. Diese Ebenen umfassen APC_LEVEL, DISPATCH_LEVEL oder WAKE_LEVEL für das Kerneldebugging. Geräteunterbrechungen haben nach wie vor höhere IRQL-Werte. Der Kernel behält sich die höchsten IRQL-Werte für systemkritische Unterbrechungen vor, z. B. bei Systemuhr- oder Busfehlern.

Einige Systemunterstützungsroutinen werden bei IRQL=PASSIVE_LEVEL ausgeführt, entweder weil sie als auslagerbarer Code implementiert oder auf auslagerbare Daten zugreifen, oder weil einige Kernelmoduskomponenten ihre eigenen Threads eingerichtet haben.

Ebenso werden einige Standardtreiberroutinen in der Regel bei IRQL=PASSIVE_LEVEL ausgeführt. Mehrere Standardtreiberroutinen werden jedoch entweder bei IRQL=DISPATCH_LEVEL oder für einen Treiber auf niedrigster Ebene auf dem Geräte-IRQL (auch DIRQL bezeichnet) ausgeführt. Weitere Informationen zu IRQLs finden Sie unter Verwalten von Hardwareprioritäten.

Jede Routine in einem Treiber ist unterbrechungsfähig. Dazu gehören alle Routinen, die bei einer höheren IRQL ausgeführt werden als PASSIVE_LEVEL. Jede Routine, die bei einem bestimmten IRQL ausgeführt wird, behält die Kontrolle über den Prozessor nur bei, wenn während der Ausführung dieser Routine keine Unterbrechung für eine höhere IRQL auftritt.

Im Gegensatz zu den Treibern in einigen älteren Betriebssystemen des Personal Computers ist die ISR eines Microsoft Windows-Treibers nie eine große, komplexe Routine, die den Großteil der Eingabe/Ausgabe-Verarbeitung des Treibers ausführt. Dies liegt daran, dass die Unterbrechungsdienstroutine (ISR) eines Treibers durch eine andere Routine (z. B. durch den ISR eines anderen Treibers) unterbrochen werden kann, die bei einem höheren IRQL ausgeführt wird. Daher behält der ISR des Treibers nicht unbedingt die Kontrolle über eine CPU, unterbrechungsfrei, vom Anfang seines Ausführungspfads bis zum Ende.

Bei Windows-Treibern speichert ein ISR in der Regel Hardwarestatusinformationen, stellt einen verzögerten Prozeduraufruf (Deferred Procedure Call, DPC) in die Warteschlange und endet dann schnell. Später wartet das System den DPC des Treibers aus, sodass der Treiber I/O-Vorgänge bei einem niedrigeren IRQL (DISPATCH_LEVEL) abschließen kann. Für eine gute Gesamtsystemleistung müssen alle Routinen, die mit hohen IRQLs ausgeführt werden, schnell die Kontrolle über die CPU aufgeben.

In Windows verfügen alle Threads über einen Threadkontext. Dieser Kontext besteht aus Informationen, die den Prozess identifizieren, der den Thread besitzt, sowie andere Merkmale wie die Zugriffsrechte des Threads.

Im Allgemeinen wird nur ein Treiber der höchsten Ebene im Kontext des Threads aufgerufen, der den aktuellen E/A-Vorgang des Treibers anfordert. Ein Treiber auf mittlerer oder niedrigster Ebene kann niemals davon ausgehen, dass er im Kontext des Threads ausgeführt wird, der den aktuellen E/A-Vorgang angefordert hat.

Daher werden Treiberroutinen in der Regel in einem beliebigen Threadkontext ausgeführt – der Kontext des aktuellen Threads, wenn eine Standardtreiberroutine aufgerufen wird. Aus Leistungsgründen (um Kontextwechsel zu vermeiden), richten nur sehr wenige Treiber ihre eigenen Threads ein.