web-dev-qa-db-fra.com

En quoi consiste exactement IRQL_NOT_LESS_OR_EQUAL?

En quoi consiste exactement IRQL_NOT_LESS_OR_EQUAL? Qu'est ce que l'IRQL? Quelles choses utilisent IRQL? Pourquoi doit-il être inférieur ou égal? Qu'est-ce qui ferait qu'il ne soit pas inférieur ou égal? Pourquoi le système d'exploitation ne peut-il pas s'en remettre s'il n'est pas inférieur ou égal? IRQL n'affecte-t-il que Windows?

Cette erreur semble être assez commune . Je ne demande pas d'aide, je demande une explication.

14
Aaron Franke

C'est compliqué. ;)

Non, vraiment, ça l'est.

IRQL signifie "Niveau de demande d'interruption". Il s’agit d’un nombre compris entre 0 et 31 sur les systèmes Windows x86 et entre 0 et 15 sur les systèmes x64. Il représente "l'importance" d'une tâche en mode noyau par rapport à d'autres tâches en mode noyau.

IRQL est un état défini par Windows du processeur - et non d'un processus ou d'un thread - qui indique à Windows si tout ce que ce processeur est en train de faire peut être interrompu par d'autres tâches. Si une nouvelle tâche (telle qu'une routine de service d'interruption) a un IRQL supérieur à l'IRQL actuel du processeur, alors oui, elle peut interrompre la tâche en cours; sinon non Sur un système multiprocesseur, chaque processeur a son propre IRQL. Cela inclut les "processeurs logiques" créés par hyperthreading.

(J'utilise le mot "importance" plutôt que "priorité" car "priorité" dans Windows fait référence aux priorités des threads, et les IRQL sont quelque chose de différent. Contrairement aux priorités des threads, les tâches du noyau dans le même IRQL ne sont pas découpées dans le temps, et les IRQL sont ' t sujet à boost automatique et la décroissance.)

(Je devrais également mentionner que le terme "tâche du noyau" n'est pas officiel ici. Windows n'appelle pas vraiment ces choses "tâches du noyau", ce ne sont pas des objets gérés comme sont par exemple des processus et des threads, et il n'y a pas de relation avec la tâche "x86" portes "ni à quoi que ce soit montré dans" Gestionnaire des tâches ". Comme je (et d'autres) utilise le terme ici," tâche en mode noyau "couvre vraiment" tout ce qui a un début et une fin définis qui doit être fait en mode noyau avec IRQL 2 ou ci-dessus. "Une routine de service d'interruption est un exemple d'une" tâche en mode noyau "; il en est de même d'une routine DPC. Mais un autre exemple peut être du code dans un thread en mode noyau. Ces threads commencent à IRQL 0, mais font partie du code soulève en IRQL 2 ou supérieur, fait quelque chose, puis revient à son précédent IRQL, la partie haute du code IRQL est un exemple de ce que je appelle une "tâche du noyau" ici.)

L'Analyseur de performances affiche le temps passé à IRQL 2 sous la forme "% temps DPC" et le temps à IRQL> 2 sous la forme "% temps d'interruption", que le temps ait été réellement passé dans une routine DPC ou dans un ISR, ou qu'il soit le résultat d'une augmentation de IRQL à partir de une valeur inférieure. Chacune est un sous-ensemble de ce que PerfMon affiche comme "% de temps privilégié" - qui aurait dû être intitulé "heure du mode noyau".

Une fois qu'une tâche du noyau est démarrée sous IRQL 2 ou supérieur, elle s'exécute avant toute autre opération sous identique IRQL sera démarré sur le même processeur. Il peut être interrompu par une tâche IRQL supérieure (qui peut à son tour être interrompue par une tâche IRQL supérieure, etc.), mais lorsque les tâches IRQL supérieures sont terminées, le contrôle revient à la tâche interrompue.

IRQL est principalement un mécanisme de sérialisation . (Beaucoup disent "synchronisation", mais je préfère ce mot car il décrit plus précisément le résultat.) Son but est de garantir que plusieurs tâches sur le même processeur accèdent à certaines ressources partagées - principalement des structures de données partagées dans l'espace noyau du système d'exploitation - ne sont pas autorisés à s'interrompre de manière à corrompre ces structures.

Par exemple, de nombreuses données dans le noyau Windows, en particulier les données de gestion de la mémoire et les données utilisées par le planificateur de threads, sont "sérialisées" à IRQL 2. Cela signifie que toute tâche qui souhaite modifier de telles données doit être exécutée sous IRQL 2. Si une tâche IRQL supérieure tente d'écrire de telles données, cela pourrait entraîner une corruption, car elle aurait pu interrompre une tâche IRQL 2 susceptible de se dérouler au milieu d'un cycle de lecture-modification-écriture sur ces mêmes données. Donc, les tâches IRQL supérieures ne sont tout simplement pas autorisées à le faire.

Les tâches IRQL plus élevées sont principalement les routines de service d'interruption des pilotes de périphérique, car toutes les interruptions de périphériques se produisent à IRQL> 2. Cela inclut l'interruption de la puce de la minuterie de la carte mère qui contrôle le chronométrage et l'activité dans le système d'exploitation. Son IRQL est supérieur à celui de tous les périphériques matériels "ordinaires".

Les IRQL 2 et supérieurs sont utilisés pour les tâches du noyau qui ne sont pas déclenchées par des interruptions matérielles, mais au cours desquelles la planification de thread normale, y compris l'attente, ne peut pas se produire. Ainsi, une fois qu'un processeur est à IRQL 2 ou supérieur, aucun changement de contexte de thread ne peut avoir lieu sur ce processeur tant que IRQL n'est pas inférieur à 2.

Le code en mode utilisateur est toujours à IRQL 0. Le code en mode noyau peut s'exécuter à partir de 0 à n'importe quel IRQL, quel que soit le max. IRQL 1 est un cas particulier; il s'agit uniquement du mode noyau, mais n'a pas d'incidence sur la planification. Il s'agit en réalité davantage d'un état de thread que de processeur - il est enregistré et restauré lors de commutations de contexte de thread, par exemple.

Afin de maintenir diverses garanties de sérialisation, la plupart des exceptions (des choses comme la division par zéro ou les violations d'accès à la mémoire comme les fautes de page) ne sont tout simplement pas gérables à partir d'IRQL 2 ou supérieur. (IRQL 2 btw est communément appelé "niveau de répartition" ou "niveau de DPC").

Et maintenant, nous pouvons enfin expliquer ce code d'erreur!

Le cas le plus courant d’IRQL_NOT_LESS_OR_EQUAL est dû à une erreur de page (tentative d’accès à une adresse virtuelle "non résident") ou à une violation d’accès à la mémoire (tentative d’écriture dans une page en lecture seule ou d’accès à une page non définie). du tout), cela se produit à IRQL 2 ou supérieur.

Si de telles exceptions sont levées avec IRQL 0 ou 1, elles peuvent être "gérées" par le code fourni par le système (comme le gestionnaire de fautes de page) ou par un gestionnaire d'exceptions fourni par le développeur. Cependant, la plupart des exceptions ne peuvent pas être gérées si elles se sont produites à partir de IRQL 2 ou supérieur.

Donc ... le code de contrôle de bogue signifie "une exception d'un type qui ne peut être gérée que si IRQL 0 ou 1 s'est produite lorsque IRQL était à 2 ou plus." c'est-à-dire "pas moins que ou égal à 1". Un libellé étrange, mais voilà.

Cette anomalie peut également déclencher cette vérification d'erreur, et la valeur pour laquelle IRQL n'est pas inférieur ou égal n'est pas toujours égale à 1, mais elles ne surviennent que rarement. La documentation WinDBG les répertorie.

21
Jamie Hanrahan