IRQL_NOT_LESS_OR_EQUAL到底是什么?什么是IRQL?什么东西使用IRQL?为什么需要小于或等于?是什么导致它不小于或等于?为什么操作系统无法从不小于或相等的状态恢复?IRQL仅影响Windows吗?
这个错误似乎很常见。我不是在寻求帮助,而是在寻求解释。
IRQL_NOT_LESS_OR_EQUAL到底是什么?什么是IRQL?什么东西使用IRQL?为什么需要小于或等于?是什么导致它不小于或等于?为什么操作系统无法从不小于或相等的状态恢复?IRQL仅影响Windows吗?
这个错误似乎很常见。我不是在寻求帮助,而是在寻求解释。
Answers:
情况很复杂。;)
不,是这样。
IRQL代表“中断请求级别”。它是一个数字,在Windows x86系统上从0到31,在x64系统上从0到15。它表示内核模式任务相对于其他内核模式任务的“重要性”。
IRQL是Windows定义的处理器状态,而不是进程或线程的状态,它向Windows指示该处理器正在执行的操作是否可以被其他任务中断。如果新任务(例如中断服务程序)的IRQL高于处理器当前的IRQL,则可以,它可以中断当前任务;否则,它可以中断当前任务。否则没有。在多处理器系统上,每个处理器都有自己的IRQL。这包括通过超线程创建的“逻辑处理器”。
(我使用“重要性”而不是“优先级”一词,因为Windows中的“优先级”指的是线程优先级,并且IRQL有所不同。与线程优先级不同,同一IRQL上的内核任务不是按时间划分的,而IRQL则不是“会自动增强和衰减。)
(我还应该提到,这里的“内核任务”一词不是官方的。Windows并没有真正将这些东西称为“内核任务”,它们不是诸如进程和线程之类的托管对象,并且与“ x86”任务没有任何关系。我(和其他人)在这里使用该术语时,“内核模式任务”实际上涵盖“需要在IRQL 2或更高版本的内核模式下完成且具有定义的开始和结束的任何内容。中断服务例程是“内核模式任务”的一个示例; DPC例程也是一个示例。但是另一个示例可以是内核模式线程中的代码。此类线程从IRQL 0开始,但是如果代码的一部分加薪到IRQL 2或更高版本,执行某些操作,然后返回其先前的IRQL,代码的高IRQL部分就是我在此处所谓的“内核任务”的一个示例。)
性能监视器将在IRQL 2上花费的时间显示为“%DPC时间”,将在IRQL 2上花费的时间显示为“%中断时间”,而不管该时间是实际花费在DPC例程还是ISR上,还是由于将IRQL从较低的值。每个都是PerfMon显示为“特权时间百分比”的子集-应该将其标记为“内核模式时间”。
一旦在IRQL 2或更高版本上启动了内核任务,它就会运行完成,然后再在同一处理器上启动同一 IRQL上的其他任何任务。它可能会被更高IRQL任务打断(反过来又可能会被更高IRQL任务打断,等等),但是当更高IRQL任务完成时,控制权将返回到被中断的任务。
IRQL主要是一种序列化机制。(很多人说“同步”,但是我更喜欢用这个词来描述结果)。它的目的是帮助确保同一CPU上的多个任务可以访问某些共享资源-大多数是OS内核空间中的共享数据结构-不允许以可能破坏这些结构的方式互相干扰。
例如,Windows内核中的大量数据,特别是内存管理数据和线程调度程序使用的数据,在IRQL 2处被“序列化”。这意味着任何想要修改此类数据的任务都必须在IRQL 2这样做时。如果较高IRQL任务尝试写入此类数据,则可能会导致损坏,因为它可能中断了IRQL 2任务,该任务可能处于对该数据进行读-修改-写周期的中间。因此,根本不允许更高IRQL任务执行此操作。
高IRQL任务主要是设备驱动程序的中断服务例程,因为所有设备的中断都在IRQL> 2时发生。这包括来自主板上计时器芯片的中断,该中断在OS中驱动计时和时间驱动活动。它的IRQL高于所有“普通”硬件设备的IRQL。
IRQL 2及更高版本用于不是由硬件中断触发的内核任务,但是在此期间无法进行正常的线程调度(包括等待)。因此,一旦处理器达到IRQL 2或更高,在IRQL降至2以下之前,该处理器上将不会发生线程上下文切换。
用户模式代码始终为IRQL0。内核模式代码可以在0到最大值之间的任何IRQL上运行。IRQL 1是特例;它仅是内核模式,但对调度没有影响,实际上它实际上是线程的状态,而不是处理器的状态-例如,在线程上下文切换期间保存和恢复该状态。
为了维护各种序列化保证,大多数异常(诸如被零除的事物或诸如页面错误之类的内存访问冲突)在IRQL 2或更高版本中根本无法处理。(IRQL 2 btw通常称为“调度级别”或“ DPC级别”。)
现在我们终于可以解释这个错误检查代码了!
IRQL_NOT_LESS_OR_EQUAL的最常见情况是由于页面错误(试图访问“非驻留”虚拟地址)或内存访问冲突(试图写入只读页面或访问未定义的页面)完全不存在),这发生在IRQL 2或更高级别。
如果此类异常在IRQL 0或1处引发,则可以通过系统提供的代码(如页面错误处理程序)或由开发人员提供的异常处理程序来“处理”它们。但是,如果大多数异常发生在IRQL 2或更高版本,则根本无法处理。
所以...错误检查代码的意思是“当IRQL为2或更高时,发生了只能在IRQL 0或1处理的类型异常”。即“不小于或等于1”。奇怪的措辞,但确实如此。
还有一些其他事情可以触发此错误检查,并且IRQL不小于或等于的值并不总是1,但它们很少发生。WinDBG文档列出了它们。