共用方式為


顯示重大區段

關鍵區段可以透過各種不同的方法,以使用者模式顯示。 每個欄位的確切意義取決於您所使用的 Microsoft Windows 版本版本。

顯示重要區段

重要區段可由 !ntsdexts.locks 延伸模組、 !critsec 延伸模組、 !cs 延伸模組和 dt (顯示類型) 命令顯示

!ntsdexts.locks延伸模組會顯示與目前進程相關聯的重要區段清單。 如果使用 -v 選項,則會顯示所有重要區段。 以下是範例:

0:000> !locks

CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount          0
RecursionCount     1
OwningThread       c78
EntryCount         0
ContentionCount    0
*** Locked

....
Scanned 37 critical sections

如果您知道想要顯示的重要區段位址,您可以使用 !critsec 延伸模組。 這會顯示與 !ntsdexts.locks相同的資訊集合。 例如:

0:000> !critsec 77fc49e0

CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount          0
RecursionCount     1
OwningThread       c78
EntryCount         0
ContentionCount    0
*** Locked

!cs延伸模組可以根據其位址顯示重要區段、搜尋重要區段的位址範圍,甚至顯示與每個重要區段相關聯的堆疊追蹤。 其中有些功能需要完整的 Windows 符號才能正常運作。 如果應用程式驗證器為使用中, !cs -t 可用來顯示重要區段樹狀結構。 如需詳細資料和範例,請參閱 !cs 參考頁面。

!cs所顯示的資訊與!ntsdexts.locks!critsec所顯示的資訊稍有不同。 例如:

## 0:000> !cs 77fc49e0

Critical section   = 0x77fc49e0 (ntdll!FastPebLock+0x0)
DebugInfo          = 0x77fc3e00
LOCKED
LockCount          = 0x0
OwningThread       = 0x00000c78
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000

dt (顯示類型) 命令可用來顯示RTL_CRITICAL_SECTION結構的常值內容。 例如:

0:000> dt RTL_CRITICAL_SECTION 77fc49e0
   +0x000 DebugInfo        : 0x77fc3e00 
   +0x004 LockCount        : 0
   +0x008 RecursionCount   : 1
   +0x00c OwningThread     : 0x00000c78 
   +0x010 LockSemaphore    : (null) 
   +0x014 SpinCount        : 0

解譯 Windows XP 和 Windows 2000 中的重要區段欄位

重要區段結構最重要的欄位如下所示:

  • 在 Microsoft Windows 2000 和 Windows XP 中, LockCount 欄位指出任何執行緒已針對此重要區段呼叫 EnterCriticalSection 常式的次數減一。 此欄位從 -1 開始進行解除鎖定的重要區段。 EnterCriticalSection的每個呼叫都會遞增此值;LeaveCriticalSection的每個呼叫都會遞減。 例如,如果 LockCount 為 5,此重大區段會鎖定,一個執行緒已取得它,而有五個額外的執行緒正在等候此鎖定。

  • RecursionCount欄位指出擁有線程為此重要區段呼叫 EnterCriticalSection的次數。

  • EntryCount欄位指出擁有線程以外的執行緒為此重要區段呼叫EnterCriticalSection的次數。

新初始化的重要區段看起來如下:

0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount          NOT LOCKED 
RecursionCount     0
OwningThread       0
EntryCount         0
ContentionCount    0

偵錯工具會顯示 「NOT LOCK」 做為 LockCount的值。 已解除鎖定關鍵區段此欄位的實際值為 -1。 您可以使用 dt (顯示類型) 命令來確認:

0:000> dt RTL_CRITICAL_SECTION 433e60
   +0x000 DebugInfo        : 0x77fcec80
   +0x004 LockCount        : -1
   +0x008 RecursionCount   : 0
   +0x00c OwningThread     : (null) 
   +0x010 LockSemaphore    : (null) 
   +0x014 SpinCount        : 0

當第一個執行緒呼叫 EnterCriticalSection 常式時,關鍵區段的 LockCountRecursionCountEntryCountContentionCount 欄位都會遞增一個, 而 OwningThread 會變成呼叫端的執行緒識別碼。 EntryCountContentionCount 永遠不會遞減。 例如:

0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount          0
RecursionCount     1
OwningThread       4d0
EntryCount         0
ContentionCount    0

此時,可能會發生四個不同的事。

  1. 擁有線程會再次呼叫 EnterCriticalSection 。 這會遞增 LockCountRecursionCountEntryCount 不會遞增。

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          1
    RecursionCount     2
    OwningThread       4d0
    EntryCount         0
    ContentionCount    0
    
  2. 不同的執行緒會呼叫 EnterCriticalSection。 這會遞增 LockCountEntryCountRecursionCount 不會遞增。

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          1
    RecursionCount     1
    OwningThread       4d0
    EntryCount         1
    ContentionCount    1
    
  3. 擁有線程會呼叫 LeaveCriticalSection。 這會將 LockCount (遞減至 -1) , 而 RecursionCount (為 0) ,並將 OwningThread 重設為 0。

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          NOT LOCKED 
    RecursionCount     0
    OwningThread       0
    EntryCount         0
    ContentionCount    0
    
  4. 另一個執行緒會呼叫 LeaveCriticalSection。 這會產生與呼叫 LeaveCriticalSection 的擁有線程相同的結果- 它會將 LockCount (遞減為 -1) ,而 RecursionCount (為 0) ,並將 OwningThread 重設為 0。

當任何執行緒呼叫 LeaveCriticalSection時,Windows 會遞減 LockCountRecursionCount。 這項功能同時具有良好和不良層面。 它可讓裝置驅動程式在一個執行緒上輸入關鍵區段,並將重大區段保留在另一個執行緒上。 不過,您也可以不小心在錯誤的執行緒上呼叫 LeaveCriticalSection ,或呼叫 LeaveCriticalSection 太多次,並導致 LockCount 達到低於 -1 的值。 這會損毀重大區段,並導致所有線程無限期地在重大區段上等候。

解譯 Windows Server 2003 SP1 和更新版本中的重要區段欄位

在 Microsoft Windows Server 2003 Service Pack 1 和更新版本的 Windows 中, [LockCount ] 欄位會剖析如下:

  • 最低位會顯示鎖定狀態。 如果此位為 0,則會鎖定重大區段;如果為 1,則重要區段不會鎖定。

  • 下一個位會顯示執行緒是否已為此鎖定喚醒。 如果此位為 0,則此鎖定已喚醒執行緒;如果為 1,則未喚醒任何執行緒。

  • 其餘位是等候鎖定之執行緒數目的補數。

例如,假設 LockCount 是 -22。 您可以透過下列方式判斷最低位:

0:009> ? 0x1 & (-0n22)
Evaluate expression: 0 = 00000000

以這種方式可以判斷下一個最低位:

0:009> ? (0x2 & (-0n22)) >> 1
Evaluate expression: 1 = 00000001

其餘位的補數可以透過下列方式來決定:

0:009> ? ((-1) - (-0n22)) >> 2
Evaluate expression: 5 = 00000005

在此範例中,第一個位是 0,因此重大區段會鎖定。 第二個位為 1,因此此鎖定沒有線程被喚醒。 其餘位的補數為 5,因此有五個執行緒正在等候此鎖定。

其他資訊

如需如何偵錯重大區段逾時的詳細資訊,請參閱 重大區段逾時。 如需重要區段的一般資訊,請參閱Microsoft Windows SDK、Windows 驅動程式套件 (WDK) ,或 Mark Russinovich 和 David Central 的Microsoft Windows 內部