本文將告訴您如何使用範例偵錯工作階段找出造成下列錯誤訊息的驅動程式:
Stop
Error IRQL_NOT_LESS_OR_EQUAL (0xA) (停止錯誤 IRQL_NOT_LESS_OR_EQUAL
(0xA))
安裝驅動程式之後,不僅系統停止回應,同時還在
nt!KiActivateWaiterQueue+0x27 中收到下列錯誤訊息:
Stop Error IRQL_NOT_LESS_OR_EQUAL
(0xA) (停止錯誤 IRQL_NOT_LESS_OR_EQUAL (0xA))
起始堆疊追蹤指出 Fast Fat
驅動程式發生問題。
這個問題的起因通常是驅動程式在執行工作項目之前,於相同工作項目上呼叫兩次
IoQueueWorkItem 函式或
ExQueueWorkItem 函式。
以固定方式配置
IO_WORKITEM 結構或
WORK_QUEUE_ITEM
結構的裝置驅動程式,特別容易發生這個問題。執行這類固定配置的裝置驅動程式必須能夠保證其不會在排入佇列時,嘗試使用固定配置的項目。
如果要偵錯因發生<徵狀>一節所提及之錯誤而停止回應的系統時,請依照下列步驟執行:
- 例如,假設您在安裝了名為 Xyz.sys 的驅動程式之後,造成系統停止回應,並收到上述的停止錯誤
0xA。
- 使用正確的符號啟動偵錯程式,然後依照本文稍後所述的偵錯範例執行。
此範例採用核心偵錯程式。您可以使用 KD 或 WinDbg,也可以啟用驅動程式檢查器而使用這個方法。 - 偵錯程式中的 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
- 您如果檢視步驟 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 ]
- 解除參照 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
注意 裝置物件的內容不會顯示本身是否為有效的裝置物件。但 [內容] 欄位為有效,而 !pool 命令則會顯示 Culprit Pool Tag 的集區標籤。 - 如果要判斷常式位址有效與否,請對集區位址使用 ln 命令。如果您擁有符號,則對集區位址使用 ln 命令所產生的結果,應與發生錯誤之驅動程式的位址相對應。因此,從過去經驗判斷,IO_WORKITEM 應會對應到某些由集區標籤中之驅動程式所驅動的裝置。
- 下列程式碼中的工作佇列包含單一項目。因此,找出問題最簡單的方法,便是取消參照 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)
錯誤而停止,請關閉並取代偵錯工作階段所找到的錯誤裝置驅動程式。
如需詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
314063?
(http://support.microsoft.com/kb/314063/
)
Windows XP 中 Stop 0x0000000A 錯誤的疑難排解
如需有關 Windows DDK 的詳細資訊及文件說明,請造訪下列 MSDN 網站: