Was genau ist IRQL_NOT_LESS_OR_EQUAL? Was ist IRQL? Welche Dinge nutzen IRQL? Warum muss es kleiner oder gleich sein? Was würde dazu führen, dass es nicht kleiner oder gleich ist? Warum kann sich das Betriebssystem nicht davon erholen, wenn es nicht kleiner oder gleich ist? Betrifft IRQL nur Windows?
Dieser Fehler scheint ziemlich häufig zu sein . Ich bitte nicht um Hilfe, ich bitte um eine Erklärung.
Antworten:
Es ist kompliziert. ;)
Nein, das ist es wirklich.
IRQL steht für "Interrupt Request Level". Diese Zahl reicht von 0 bis 31 auf Windows x86-Systemen und von 0 bis 15 auf x64-Systemen. Es repräsentiert die "Wichtigkeit" einer Kernelmodus-Aufgabe im Verhältnis zu anderen Kernelmodus-Aufgaben.
IRQL ist ein Windows-definierter Status des Prozessors - nicht eines Prozesses oder Threads -, der Windows angibt, ob der Prozessor durch andere Aufgaben unterbrochen werden kann oder nicht. Wenn eine neue Task (z. B. eine Interrupt-Serviceroutine) eine höhere IRQL als die aktuelle IRQL des Prozessors hat, kann sie die aktuelle Task unterbrechen. sonst nein. Auf einem Multiprozessorsystem hat jeder Prozessor seine eigene IRQL. Dies schließt die durch Hyperthreading erstellten "logischen Prozessoren" ein.
(Ich verwende das Wort "Wichtigkeit" anstatt "Priorität", weil "Priorität" in Windows sich auf Thread-Prioritäten bezieht und IRQLs etwas anderes sind. Im Gegensatz zu Thread-Prioritäten werden Kernel-Tasks auf derselben IRQL nicht zeitlich getrennt und IRQLs sind nicht " t unterliegt automatischem Boost und Decay.)
(Ich sollte auch erwähnen, dass der Begriff "Kernel-Task" hier nicht offiziell ist. Windows nennt diese Dinge nicht wirklich "Kernel-Tasks", es handelt sich nicht um verwaltete Objekte, wie z. B. Prozesse und Threads, und es besteht keine Beziehung zur x86-Task Da ich (und andere) hier den Begriff "Kernel-Modus-Task" verwende "alles mit einem definierten Anfang und Ende, das im Kernel-Modus bei IRQL 2 oder 4 ausgeführt werden muss "Eine Interrupt-Service-Routine ist ein Beispiel für eine" Kernel-Mode-Task ", ebenso eine DPC-Routine. Ein anderes Beispiel kann Code in einem Kernel-Mode-Thread sein. Solche Threads beginnen bei IRQL 0, sind jedoch Teil des Codes wirftzu IRQL 2 oder höher führt etwas aus und kehrt dann zu seinem vorherigen IRQL zurück. Der High-IRQL-Teil des Codes ist ein Beispiel für das, was ich hier als "Kernel-Task" bezeichne. )
Der Systemmonitor zeigt die in IRQL 2 verbrachte Zeit als "% DPC-Zeit" und die in IRQL> 2 verbrachte Zeit als "% Interrupt-Zeit" an, unabhängig davon, ob die Zeit tatsächlich in einer DPC-Routine oder einem ISR verbracht wurde oder das Ergebnis der Erhöhung von IRQL von ein niedrigerer Wert. Jedes ist eine Teilmenge dessen, was PerfMon als "% privilegierte Zeit" anzeigt - was als "Kernelmoduszeit" hätte bezeichnet werden sollen.
Sobald eine Kernel-Task mit IRQL 2 oder höher gestartet wurde, wird sie vollständig ausgeführt, bevor andere Aufgaben mit demselben IRQL auf demselben Prozessor gestartet werden. Es kann durch eine Task mit höherem IRQL-Wert unterbrochen werden (die wiederum durch eine Task mit höherem IRQL-Wert usw. unterbrochen werden könnte), aber wenn die Tasks mit höherem IRQL-Wert abgeschlossen sind, kehrt die Steuerung zu der Task zurück, die es unterbrochen hat.
IRQL ist in erster Linie ein Serialisierungsmechanismus . (Viele sagen "Synchronisation", aber ich bevorzuge dieses Wort, da es das Ergebnis genauer beschreibt.) Es soll sicherstellen, dass mehrere Tasks auf derselben CPU auf bestimmte gemeinsam genutzte Ressourcen zugreifen - meistens gemeinsam genutzte Datenstrukturen im Betriebssystemkern -. dürfen sich nicht gegenseitig auf eine Weise unterbrechen, die diese Strukturen beschädigen könnte.
Beispielsweise werden viele Daten im Windows-Kernel, insbesondere die Speicherverwaltungsdaten und die vom Thread-Scheduler verwendeten Daten, bei IRQL 2 "serialisiert" . Das bedeutet, dass jede Task, die solche Daten ändern möchte, bei ausgeführt werden muss IRQL 2, wenn es das tut. Wenn eine Task mit höherem IRQL-Wert versucht, solche Daten zu schreiben, kann dies zu Beschädigungen führen, da möglicherweise eine IRQL 2-Task unterbrochen wurde, die sich in der Mitte eines Lese-, Änderungs- und Schreibzyklus für dieselben Daten befindet. Aufgaben mit höherem IRQL-Wert dürfen das einfach nicht.
Aufgaben mit höherem IRQL-Wert sind meist die Interrupt-Serviceroutinen von Gerätetreibern, da alle Geräte-Interrupts bei IRQL> 2 auftreten. Dies schließt den Interrupt vom Timer-Chip auf der Hauptplatine ein, der die Zeitmessung und die zeitgesteuerte Aktivität im Betriebssystem steuert. Sein IRQL liegt über dem aller "normalen" Hardwaregeräte.
IRQLs 2 und höher werden für Kernel-Tasks verwendet, die nicht durch Hardware-Interrupts ausgelöst werden, bei denen jedoch keine normale Thread-Planung - einschließlich Warten - stattfinden kann. Sobald sich ein Prozessor in IRQL 2 oder höher befindet, können auf diesem Prozessor keine Thread-Kontextwechsel mehr stattfinden, bis IRQL unter 2 fällt.
Der Benutzermoduscode ist immer auf IRQL 0. Der Kernelmoduscode kann bei jedem IRQL von 0 bis zu einem beliebigen Maximalwert ausgeführt werden. IRQL 1 ist ein Sonderfall. Dies ist nur der Kernel-Modus, hat jedoch keine Auswirkungen auf die Zeitplanung und ist eigentlich eher ein Status eines Threads als des Prozessors - er wird beispielsweise bei Thread-Kontextwechseln gespeichert und wiederhergestellt.
Um verschiedene Serialisierungsgarantien aufrechtzuerhalten, sind die meisten Ausnahmen (z. B. Division durch Null oder Speicherzugriffsverletzungen wie Seitenfehler) in IRQL 2 oder höher einfach nicht behandelbar. (IRQL 2 wird im Allgemeinen als "Versandebene" oder "DPC-Ebene" bezeichnet.)
Und jetzt können wir endlich diesen Bugcheck-Code erklären!
Der häufigste Fall von IRQL_NOT_LESS_OR_EQUAL ist auf einen Seitenfehler (Versuch, auf eine "nicht residente" virtuelle Adresse zuzugreifen) oder eine Speicherzugriffsverletzung (Versuch, auf eine schreibgeschützte Seite zu schreiben oder auf eine nicht definierte Seite zuzugreifen) zurückzuführen überhaupt), der bei IRQL 2 oder höher auftritt.
Wenn solche Ausnahmen bei IRQL 0 oder 1 ausgelöst werden, können sie entweder von einem vom System bereitgestellten Code (wie dem Page Fault Handler) oder von einem vom Entwickler bereitgestellten Exception Handler "behandelt" werden. Die meisten Ausnahmen können jedoch überhaupt nicht behandelt werden, wenn sie bei IRQL 2 oder höher aufgetreten sind.
Also ... der Bugcheck-Code bedeutet "eine Ausnahme von einem Typ, der nur bei IRQL 0 oder 1 behandelt werden kann, wenn IRQL 2 oder höher war." dh "nicht weniger als oder gleich 1". Seltsame Formulierung, aber da ist es.
Es gibt einige andere Dinge, die diesen Bugcheck auslösen können, und der Wert, mit dem der IRQL-Wert nicht kleiner oder gleich ist, ist nicht immer 1, aber sie treten nur selten auf. Die WinDBG-Dokumentation listet sie auf.
quelle