!僵局
!deadlock 擴充功能會顯示驅動程序驗證器死結偵測選項所收集之死結的相關信息。
!deadlock
!deadlock 1
DLL
Kdexts.dll
其他資訊
如需驅動程式驗證器的相關信息,請參閱 Windows 驅動程式套件 (WDK) 檔。
備註
只有在驅動程式驗證工具的 死結偵測 選項偵測到鎖定階層違規,併發出 錯誤檢查0xC4 (DRIVER_VERIFIER_DETECTED_VIOLATION) 時,此延伸模組才會提供有用的資訊。
如果沒有任何自變數, !死結 擴充功能會導致顯示基本鎖定階層拓撲。 如果問題不是簡單的迴圈死結,此命令將會描述已發生的情況。
!deadlock 1 延伸模組會導致顯示堆棧追蹤。 顯示的堆疊將會是取得鎖定時作用中的堆疊。
以下是範例:
0:kd> !deadlock
Deadlock detected (2 resources in 2 threads):
Thread 0: A B
Thread 1: B A
Where:
Thread 0 = 8d3ba030
Thread 1 = 8d15c030
Lock A = bba2af30 Type 'Spinlock'
Lock B = dummy!GlobalLock Type 'Spinlock'
這會告訴您涉及哪些線程和哪些鎖定。 不過,它是摘要,可能沒有足夠的資訊來充分偵錯情況。
使用 !deadlock 1 列印在取得參與死結之每個鎖定時呼叫堆棧的內容。 因為這些是運行時間堆疊追蹤,所以如果使用檢查的組建,它們將會更完整。 在 Windows 10 版本 1803 之前,檢查過的組建可在舊版 Windows 上使用。 在免費組建中,它們可能會在一行之後被截斷。
0:kd> !deadlock 1
Deadlock detected (2 resources in 2 threads):
Thread 0 (8D14F750) took locks in the following order:
Lock A -- b7906f30 (Spinlock)
Stack: dummy!DummyActivateVcComplete+0x63
dummy!dummyOpenVcChannels+0x2E1
dummy!DummyAllocateRecvBufferComplete+0x436
dummy!DummyAllocateComplete+0x55
NDIS!ndisMQueuedAllocateSharedHandler+0xC9
NDIS!ndisWorkerThread+0xEE
Lock B -- dummy!GlobalLock (Spinlock)
Stack: dummy!dummyQueueRecvBuffers+0x2D
dummy!DummyActivateVcComplete+0x90
dummy!dummyOpenVcChannels+0x2E1
dummy!DummyAllocateRecvBufferComplete+0x436
dummy!DummyAllocateComplete+0x55
Thread 1 (8D903030) took locks in the following order:
Lock B -- dummy!GlobalLock (Spinlock)
Stack: dummy!dummyRxInterruptOnCompletion+0x25D
dummy!DummyHandleInterrupt+0x32F
NDIS!ndisMDpcX+0x3C
ntkrnlpa!KiRetireDpcList+0x5D
Lock A -- b7906f30 (Spinlock)
Stack: << Current stack >>
有了這項資訊,除了目前的堆疊之外,您幾乎擁有所需的一切:
0: kd> k
ChildEBP RetAddr
f78aae6c 80664c58 ntkrnlpa!DbgBreakPoint
f78aae74 8066523f ntkrnlpa!ViDeadlockReportIssue+0x2f
f78aae9c 806665df ntkrnlpa!ViDeadlockAnalyze+0x253
f78aaee8 8065d944 ntkrnlpa!VfDeadlockAcquireResource+0x20b
f78aaf08 bfd6df46 ntkrnlpa!VerifierKeAcquireSpinLockAtDpcLevel+0x44
f78aafa4 b1bf2d2d dummy!dummyRxInterruptOnCompletion+0x2b5
f78aafc4 bfde9d8c dummy!DummyHandleInterrupt+0x32f
f78aafd8 804b393b NDIS!ndisMDpcX+0x3c
f78aaff4 804b922b ntkrnlpa!KiRetireDpcList+0x5d
您可以從中查看涉及哪些鎖定,以及其取得位置。 這應該足以讓您偵錯死結。 如果原始碼可用,您可以使用除錯程式來確切查看問題發生的位置:
0: kd> .lines
Line number information will be loaded
0: kd> u dummy!DummyActivateVcComplete+0x63 l1
dummy!DummyActivateVcComplete+63 [d:\nt\drivers\dummy\vc.c @ 2711]:
b1bfe6c9 837d0c00 cmp dword ptr [ebp+0xc],0x0
0: kd> u dummy!dummyQueueRecvBuffers+0x2D l1
dummy!dummyQueueRecvBuffers+2d [d:\nt\drivers\dummy\receive.c @ 2894]:
b1bf4e39 807d0c01 cmp byte ptr [ebp+0xc],0x1
0: kd> u dummy!dummyRxInterruptOnCompletion+0x25D l1
dummy!dummyRxInterruptOnCompletion+25d [d:\nt\drivers\dummy\receive.c @ 1424]:
b1bf5d05 85f6 test esi,esi
0: kd> u dummy!dummyRxInterruptOnCompletion+0x2b5 l1
dummy!dummyRxInterruptOnCompletion+2b5 [d:\nt\drivers\dummy\receive.c @ 1441]:
b1bf5d5d 8b4648 mov eax,[esi+0x48]
現在您知道來源檔案的名稱,以及取得所在的行號。 在此情況下,來源檔案會顯示線程的行為如下:
線程 1: DummyActivateVcComplete 採取了 虛擬迷你 埠鎖定。 然後,它被稱為 虛擬QueueRecvBuffers,它採取了 虛擬 的全球鎖定。
線程 2: dummyRxInterruptOnCompletion 擷取全域鎖定。 然後,幾行后,它採取了迷你埠鎖定。
此時,死結變得完全清楚。