症状 安装驱动程序后,系统停止响应,且在 nt!KiActivateWaiterQueue+0x27 中收到以下错误消息: Stop Error IRQL_NOT_LESS_OR_EQUAL (0xA) 初始堆栈跟踪指示此问题的根源是 Fast Fat 驱动程序
原因由于在执行工作项之前,驱动程序会对同一工作项调用 IoQueueWorkItem 函数或 ExQueueWorkItem 函数两次,因此通常会出现此问题。静态分配 IO_WORKITEM 结构或 WORK_QUEUE_ITEM 结构的设备驱动程序特别容易出现此问题。执行此静态分配的设备驱动程序必须确保它们不尝试使用已排队的静态分配项。 更多信息 要调试已经停止响应并出现“症状”中提到的错误的系统,请按照下列步骤操作: 1. 假设您安装了一个已命名的驱动程序(如 Xyz.sys),则系统会停止响应,且您会收到前面提到的 Stop 错误 0xA。 2. 使用正确的符号启动调试程序,然后遵循本文后面所介绍的调试示例。 该示例使用内核调试程序。您可以使用 KD 或 WinDbg。还可以通过启用驱动程序验证程序来使用该方法。 3. 该调试程序中的 kv 命令显示堆栈。以下堆栈跟踪指示 WORKER_QUEUE 已经损坏。
Stack Trace: f8979768 804f076c fc502008 ff651fb8 e16de008 nt!KiActivateWaiterQueue+0x27 f8979790 f8462061 00000000 00000000 00000000 nt!KeWaitForSingleObject+0x198 f89797ac f8462289 ff651fb8 00000600 ff651fb8 Fastfat!FatWaitSync+0x18 f897989c f8461e62 ff651fb8 fc502008 e16de008 Fastfat!FatNonCachedIo+0x36b f8979a2c f845b6b0 ff651fb8 fc502008 fc502008 Fastfat!FatCommonWrite+0xf29 f8979a70 804eca36 82378020 fc502008 823d1698 Fastfat!FatFsdWrite+0xaa f8979a80 f847f3b8 804f46ad f377404c f8979ab8 nt!IopfCallDriver+0x31 f8979a90 804eca36 82379a08 e27dac88 f8979aec sr!SrWrite+0xa8 f8979ad8 804f46ad f376a0a6 823cafb8 82035ca8 nt!IopfCallDriver+0x31 f8979adc f376a0a6 823cafb8 82035ca8 80570400 nt!IoSetThreadHardErrorMode 4. 如果查看步骤 3 中的堆栈,您可能会认为 Fast Fat 是错误的驱动程序。然而,KQUEUE 结构显示了一个已损坏的 LIST_ENTRY:
kd> dv Queue = ffffffff8054eddc kd> dt -r1 _KQUEUE 8054eddc +0x000 Header : +0x000 Type : 0x4 '' +0x001 Absolute : 0 '' +0x002 Size : 0xa '' +0x003 Inserted : 0 '' +0x004 SignalState : 1 +0x008 WaitListHead : _LIST_ENTRY [ 0x823cb438 - 0x823ca6b0 ] +0x010 EntryListHead : [ 0x0 - 0x820ae3c8 ] +0x000 Flink : (null) +0x004 Blink : 0x820ae3c8 [ 0x0 - 0x8054edec ] 5. 取消对 BLINK 结构的引用,该结构指向 WORK_QUEUE_ITEM(此处,它实际上是 IO_WORKITEM 中的第一个参数)。注意:IO_WORKITEM 的结构定义通过 Windows XP 和更高版本的符号服务器来实现。早期版本的 Windows 具有相同结构,但符号不可用。
kd> dt -r1 _IO_WORKITEM 820ae3c8 +0x000 WorkItem : +0x000 List : _LIST_ENTRY [ 0x0 - 0x8054edec ] +0x008 WorkerRoutine : 0x8057fb78 nt!IopProcessWorkItem+0 +0x00c Parameter : 0x820ae3c8 +0x010 Routine : 0xf289dff0 +0 +0x014 DeviceObject : 0xfe01b110 +0x000 Type : 0 +0x002 Size : 0 +0x004 ReferenceCount : 0 +0x008 DriverObject : (null) +0x00c NextDevice : (null) +0x010 AttachedDevice : 0x1fde0970 +0x014 CurrentIrp : (null) +0x018 Timer : (null) +0x01c Flags : 0 +0x020 Characteristics : 0x490049 +0x024 Vpb : 0x000c0105 +0x028 DeviceExtension : 0x0001ffff +0x02c DeviceType : 0x86a24 +0x030 StackSize : 8 '' +0x034 Queue : __unnamed +0x05c AlignmentRequirement : 0x7fffffff +0x060 DeviceQueue : _KDEVICE_QUEUE +0x074 Dpc : _KDPC +0x094 ActiveThreadCount : 0 +0x098 SecurityDescriptor : (null) +0x09c DeviceLock : _KEVENT +0x0ac SectorSize : 0 +0x0ae Spare1 : 0 +0x0b0 DeviceObjectExtension : (null) +0x0b4 Reserved : (null) +0x018 Context : 0x81f4a14c 注意:该设备对象的内容未表明它是一个有效的设备对象。但 Context 字段有效,且 !pool 命令显示了 Culprit Pool Tag 的 pooltag。 6. 要确定 Routine 地址是否有效,请对池地址使用 ln 命令。如果有符号,则对池地址使用 ln 命令的结果应对应于 culprit 驱动程序中的某个地址。因此,一个有根据的猜测是 IO_WORKITEM 对应于由池标记的驱动程序生成的某个设备。 7. 在以下代码中,工作队列包含一个项。因此,取消对 BLINK 的引用可以轻松地找到它。由于工作队列可能包含多个项,因此必须取消对每个工作项的 BLINK 的引用,直到您找到其 BLINK 指向 KQUEUE 的工作项。
kd> !pool 81f4a14c Pool page 81f4a14c region is Nonpaged pool *81f4a140 size: 2b8 previous size: 8 (Allocated) *Culprit Pool Tag 解决方案 要防止系统因此 Stop 错误而停止,请关闭通过调试会话找到的错误设备驱动程序然后替换它。
(出处:http://www.sheup.com)