중요 섹션 표시
중요한 섹션은 다양한 방법으로 사용자 모드로 표시할 수 있습니다. 각 필드의 정확한 의미는 사용 중인 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 기호가 필요합니다. Application Verifier가 활성 상태이면 !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이면 이 중요한 섹션이 잠기고, 한 스레드가 이 섹션을 획득했으며, 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
디버거는 LockCount 값으로 "NOT LOCKED"를 표시합니다. 잠금 해제된 중요 섹션에 대한 이 필드의 실제 값은 -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 루틴을 호출하면 중요한 섹션의 LockCount, RecursionCount, EntryCount 및 ContentionCount 필드가 모두 하나씩 증가하며 OwningThread 는 호출자의 스레드 ID가 됩니다. EntryCount 및 ContentionCount 는 감소되지 않습니다. 예:
0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount 0
RecursionCount 1
OwningThread 4d0
EntryCount 0
ContentionCount 0
이 시점에서 네 가지 다른 일이 발생할 수 있습니다.
소유 스레드는 EnterCriticalSection을 다시 호출합니다. 그러면 LockCount 및 RecursionCount가 증가합니다. EntryCount 가 증가하지 않습니다.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 2 OwningThread 4d0 EntryCount 0 ContentionCount 0
다른 스레드는 EnterCriticalSection을 호출합니다. 그러면 LockCount 및 EntryCount 가 증가 합니다. RecursionCount 가 증가하지 않습니다.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 1 OwningThread 4d0 EntryCount 1 ContentionCount 1
소유 스레드는 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
다른 스레드는 LeaveCriticalSection을 호출합니다. 이렇게 하면 LeaveCriticalSection 을 호출하는 소유 스레드와 동일한 결과가 생성됩니다. 그러면 LockCount (-1) 및 RecursionCount (0)가 감소하고 OwningThread 가 0으로 다시 설정됩니다.
스레드가 LeaveCriticalSection을 호출하면 Windows는 LockCount 및 RecursionCount를 감소합니다. 이 기능에는 좋은 측면과 나쁜 측면이 모두 있습니다. 디바이스 드라이버가 한 스레드에서 중요한 섹션을 입력하고 중요한 섹션을 다른 스레드에 남겨 둘 수 있습니다. 그러나 실수로 잘못된 스레드에서 LeaveCriticalSection 을 호출하거나 LeaveCriticalSection 을 너무 많이 호출하여 LockCount 가 -1보다 낮은 값에 도달할 수도 있습니다. 이렇게 하면 중요한 섹션이 손상되고 모든 스레드가 중요 섹션에서 무기한 대기합니다.
Windows Server 2003 SP1 이상에서 중요 섹션 필드 해석
Microsoft Windows Server 2003 서비스 팩 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이므로 이 잠금을 기다리는 5개의 스레드가 있습니다.
추가 정보
중요한 섹션 시간 초과를 디버그하는 방법에 대한 자세한 내용은 중요 섹션 시간 초과를 참조하세요. 중요한 섹션에 대한 일반적인 내용은 Microsoft Windows SDK, WDK(Windows 드라이버 키트) 또는 Mark Russinovich 및 David Solomon의 Microsoft Windows Internals를 참조하세요.