O que exatamente é IRQL_NOT_LESS_OR_EQUAL?

O que exatamente é IRQL_NOT_LESS_OR_EQUAL?

O que exatamente é IRQL_NOT_LESS_OR_EQUAL? O que é IRQL? Quais coisas usam IRQL? Por que precisa ser menor ou igual? O que faria com que não fosse menor ou igual? Por que o sistema operacional não consegue se recuperar de não ser menor ou igual? O IRQL afeta apenas o Windows?

Este erro parece serbastante comum. Não estou pedindo ajuda, estou pedindo uma explicação.

Responder1

É complicado. ;)

Não, realmente é.

IRQL significa “Nível de solicitação de interrupção”. É um número que varia de 0 a 31 em sistemas Windows x86 e de 0 a 15 em sistemas x64. Representa a "importância" de uma tarefa no modo kernel em relação a outras tarefas no modo kernel.

IRQL é um estado do processador definido pelo Windows - não de um processo ou thread - que indica ao Windows se tudo o que o processador está fazendo pode ou não ser interrompido por outras tarefas. Se uma nova tarefa (como uma rotina de serviço de interrupção) tiver um IRQL superior ao IRQL atual do processador, então sim, ela poderá interromper a tarefa atual; caso contrário, não. Em um sistema multiprocessador, cada processador possui seu próprio IRQL. Isso inclui os “Processadores Lógicos” criados por hyperthreading.

(Eu uso a palavra "importância" em vez de "prioridade" porque "prioridade" no Windows se refere a prioridades de thread e IRQLs são algo diferente. Ao contrário das prioridades de thread, as tarefas do kernel no mesmo IRQL não são divididas no tempo e os IRQLs são ' não está sujeito a aumento e decaimento automáticos).

(Devo mencionar também que o termo "tarefa do kernel" aqui não é oficial. O Windows realmente não chama essas coisas de "tarefas do kernel", elas não são objetos gerenciados como, por exemplo, processos e threads, e não há relação com x86 "tarefa portas" nem para nada mostrado no "Gerenciador de Tarefas". Como eu (e outros) usamos o termo aqui, "tarefa no modo kernel" realmente cobre "qualquer coisa com um começo e fim definidos que precisa ser feito no modo kernel no IRQL 2 ou acima." Uma rotina de serviço de interrupção é um exemplo de uma "tarefa de modo kernel"; assim como uma rotina DPC. Mas outro exemplo pode ser o código em um thread de modo kernel. Esses threads começam em IRQL 0, mas se fizerem parte do códigolevantapara IRQL 2 ou superior, faz alguma coisa e depois retorna ao IRQL anterior, a parte de alto IRQL do código é um exemplo do que estou chamando de "tarefa do kernel" aqui. )

O Monitor de desempenho mostra o tempo gasto no IRQL 2 como "% de tempo de DPC" e o tempo em IRQL > 2 como "% de tempo de interrupção", independentemente de o tempo ter sido realmente gasto em uma rotina de DPC ou ISR ou ter sido resultado do aumento do IRQL de um valor inferior. Cada um é um subconjunto do que o PerfMon mostra como "% de tempo privilegiado" - que deveria ter sido rotulado como "tempo do modo kernel".

Depois que uma tarefa do kernel é iniciada no IRQL 2 ou superior, ela é executada até a conclusão antes de qualquer outra coisa nomesmoIRQL será iniciado no mesmo processador. Ele pode ser interrompido por uma tarefa com IRQL mais alto (que, por sua vez, pode ser interrompida por uma tarefa com IRQL ainda mais alto, etc.), mas quando as tarefas com IRQL mais alto são concluídas, o controle retorna para a tarefa que interrompeu.

IRQL é principalmente umserializaçãomecanismo. (Muitos dizem "sincronização", mas eu prefiro esta palavra porque descreve o resultado com mais precisão.) Seu objetivo é ajudar a garantir que múltiplas tarefas na mesma CPU que acessam certos recursos compartilhados - principalmente estruturas de dados compartilhadas no espaço do kernel do sistema operacional - não estão autorizados a interromper-se mutuamente de formas que possam corromper essas estruturas.

Por exemplo, uma grande quantidade de dados no kernel do Windows, particularmente os dados de gerenciamento de memória e os dados usados ​​pelo agendador de threads, é"serializado"no IRQL 2. Isso significa que qualquer tarefa que queira modificar esses dados deve estar em execução no IRQL 2 quando o fizer. Se uma tarefa de IRQL superior tentar gravar esses dados, isso poderá causar corrupção, pois poderá ter interrompido uma tarefa IRQL 2 que pode estar no meio de um ciclo de leitura-modificação-gravação nos mesmos dados. Portanto, tarefas com IRQL mais alto simplesmente não têm permissão para fazer isso.

As tarefas de IRQL superior são principalmente rotinas de serviço de interrupção de drivers de dispositivo, porque todas as interrupções de dispositivos ocorrem em IRQL > 2. Isso inclui a interrupção do chip temporizador na placa-mãe que controla a cronometragem e a atividade orientada por tempo no sistema operacional. Seu IRQL está acima de todos os dispositivos de hardware "comuns".

IRQLs 2 e superiores são usados ​​para tarefas de kernel que não são acionadas por interrupções de hardware, mas durante as quais o agendamento normal de threads - incluindo espera - não pode ocorrer. Assim, uma vez que um processador esteja no IRQL 2 ou superior, nenhuma mudança de contexto de thread poderá acontecer nesse processador até que o IRQL caia abaixo de 2.

O código do modo de usuário está sempre em IRQL 0. O código do modo kernel pode ser executado em qualquer IRQL de 0 a qualquer que seja o máximo. IRQL 1 é um caso especial; é apenas o modo kernel, mas não tem impacto no agendamento e é realmente mais um estado de um thread do que do processador - ele é salvo e restaurado durante as trocas de contexto do thread, por exemplo.

Para manter várias garantias de serialização, a maioria das exceções (coisas como divisão por zero ou violações de acesso à memória, como falhas de página) simplesmente não podem ser tratadas no IRQL 2 ou superior. (IRQL 2 aliás é comumente chamado de "nível de despacho" ou "nível DPC".)

E agora podemos finalmente explicar esse código de verificação de bug!

O caso mais comum de IRQL_NOT_LESS_OR_EQUAL é devido a uma falha de página (tentativa de acessar um endereço virtual "não residente") ou a uma violação de acesso à memória (tentativa de gravar em uma página somente leitura ou acessar uma página que não está definida de todo), que ocorre no IRQL 2 ou superior.

Se tais exceções forem geradas no IRQL 0 ou 1, elas poderão ser "tratadas" pelo código fornecido pelo sistema (como o manipulador de falhas de página) ou por um manipulador de exceções fornecido pelo desenvolvedor. No entanto, a maioria das exceções não poderá ser tratada se ocorrerem no IRQL 2 ou superior.

Então... o código de verificação de bug significa "uma exceção de um tipo que só pode ser tratada no IRQL 0 ou 1 ocorreu quando o IRQL estava em 2 ou superior". ou seja, "não menor ou igual a 1". Texto estranho, mas aí está.

Existem algumas outras coisas que podem acionar essa verificação de bug, e o valor ao qual o IRQL não é menor ou igual nem sempre é 1, mas ocorrem apenas raramente. A documentação do WinDBG os lista.

informação relacionada