IRQL_NOT_LESS_OR_EQUAL 究竟是什么?

Aar*_*nke 23 windows crash bsod irq

IRQL_NOT_LESS_OR_EQUAL 究竟是什么?什么是IRQL?什么东西使用IRQL?为什么需要小于或等于?什么会导致它不小于或等于?为什么操作系统不能从它不小于或等于中恢复?IRQL 只影响 Windows 吗?

这个错误似乎很常见。我不是在寻求帮助,我是在寻求解释。

Jam*_*han 39

情况很复杂。;)

不,真的,确实如此。

IRQL 代表“中断请求级别”。它是一个数字,在 Windows x86 系统上从 0 到 31,在 x64 系统上从 0 到 15。它表示内核模式任务相对于其他内核模式任务的“重要性”。

IRQL 是处理器的 Windows 定义状态 - 不是进程或线程的状态 - 向 Windows 指示该处理器正在执行的任何操作是否可以被其他任务中断。如果一个新的任务(比如一个中断服务程序)的IRQL比处理器当前的IRQL高,那么是的,它可以中断当前的任务;否则没有。在多处理器系统上,每个处理器都有自己的 IRQL。这包括由超线程创建的“逻辑处理器”。

(我使用“重要性”而不是“优先级”这个词,因为 Windows 中的“优先级”指的是线程优先级,而 IRQL 是不同的。与线程优先级不同,同一 IRQL 中的内核任务没有时间分片,而 IRQL 则不是。 t 受自动升压和衰减的影响。)

(我还应该提到,这里的“内核任务”一词不是官方的。Windows 并没有真正将这些东西称为“内核任务”,它们不是像进程和线程那样的托管对象,并且与 x86 的“任务”无关门”或“任务管理器”中显示的任何内容。正如我(和其他人)在这里使用的术语,“内核模式任务”实际上涵盖了“任何需要在内核模式下在 IRQL 2 或上面。”中断服务例程是“内核模式任务”的一个示例;DPC 例程也是如此。但另一个示例可以是内核模式线程中的代码。此类线程从 IRQL 0 开始,但如果是代码的一部分加注到 IRQL 2 或更高版本,执行某些操作,然后返回到其先前的 IRQL,代码的高 IRQL 部分是我在此处称为“内核任务”的一个示例。)

性能监视器将花费在 IRQL 2 的时间显示为“% DPC 时间”,将 IRQL > 2 的时间显示为“% 中断时间”,无论该时间是实际花费在 DPC 例程或 ISR 中还是由于从较低的值。每个都是 PerfMon 显示为“特权时间百分比”的一个子集——它应该被标记为“内核模式时间”。

一旦内核任务在 IRQL 2 或更高版本上启动,它会在同一IRQL 上的任何其他内容在同一处理器上启动之前运行到完成。它可能会被更高的 IRQL 任务中断(而后者又可能被更高的 IRQL 任务中断,等等),但是当更高的 IRQL 任务完成时,控制返回到它中断的任务。

IRQL 主要是一种序列化机制。(许多人说“同步”,但我更喜欢这个词,因为它更准确地描述了结果。)它的目的是帮助保证同一 CPU 上的多个任务访问某些共享资源——主要是操作系统内核空间中的共享数据结构——不允许以可能破坏这些结构的方式相互干扰。

例如,Windows 内核中的大量数据,尤其是内存管理数据和线程调度程序使用的数据,在 IRQL 2 中被“序列化”。这意味着任何想要修改这些数据的任务都必须在IRQL 2 这样做时。如果更高的 IRQL 任务尝试写入此类数据,则可能会导致损坏,因为它可能会中断 IRQL 2 任务,而该任务可能处于对同一数据的读取-修改-写入周期的中间。所以更高 IRQL 的任务根本不允许这样做。

更高的 IRQL 任务主要是设备驱动程序的中断服务例程,因为所有设备的中断都发生在 IRQL > 2 时。这包括来自主板上的定时器芯片的中断,它驱动操作系统中的计时和时间驱动活动。它的 IRQL 高于所有“普通”硬件设备。

IRQL 2 及更高版本用于不是由硬件中断触发的内核任务,但在此期间不能发生正常的线程调度(包括等待)。因此,一旦处理器处于 IRQL 2 或更高级别,则该处理器上不会发生线程上下文切换,直到 IRQL 降至 2 以下。

用户模式代码始终处于 IRQL 0。内核模式代码可以在从 0 到最大值的任何 IRQL 上运行。IRQL 1 是一个特例;它只是内核模式,但对调度没有影响,实际上更多的是线程的状态而不是处理器的状态 - 例如,它在线程上下文切换期间被保存和恢复。

为了维护各种序列化保证,在 IRQL 2 或更高版本中,大多数异常(例如除以零,或内存访问违规,例如页面错误)根本无法处理。(IRQL 2 顺便说一句,通常称为“调度级别”或“DPC 级别”。)

现在我们终于可以解释这个错误检查代码了!

IRQL_NOT_LESS_OR_EQUAL 最常见的情况是由于页面错误(尝试访问“非驻留”虚拟地址)或内存访问冲突(尝试写入只读页面或访问未定义的页面)全部),这发生在 IRQL 2 或更高版本。

如果在 IRQL 0 或 1 处引发此类异常,则它们可以由系统提供的代码(如页面错误处理程序)或由开发人员提供的异常处理程序“处理”。但是,如果大多数异常发生在 IRQL 2 或更高版本,则根本无法处理它们。

所以......错误检查代码的意思是“当 IRQL 为 2 或更高时,只能在 IRQL 0 或 1 处处理的类型异常”。即“不小于或等于1”。奇怪的措辞,但就是这样。

还有一些其他事情可以触发此错误检查,并且 IRQL 不小于或等于的值并不总是 1,但它们很少发生。WinDBG 文档列出了它们。

  • 可能是设备驱动程序。 (2认同)
  • @LawrenceC 是的。所有硬件中断都处于 IRQL > 2。 (2认同)