Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Kritické části se dají zobrazit v uživatelském režimu různými metodami. Přesný význam jednotlivých polí závisí na verzi microsoft Windows, kterou používáte.
Zobrazení kritických oddílů
Kritické části lze zobrazit pomocí rozšíření !ntsdexts.locks, přípony !critsec, rozšíření !cs a příkazu dt (Typ zobrazení).
Rozšíření !ntsdexts.locks zobrazí seznam kritických sekcí přidružených k aktuálnímu procesu. Pokud se použije možnost -v , zobrazí se všechny důležité části. Tady je příklad:
0:000> !locks
CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount 0
RecursionCount 1
OwningThread c78
EntryCount 0
ContentionCount 0
*** Locked
....
Scanned 37 critical sections
Pokud znáte adresu kritického oddílu, který chcete zobrazit, můžete použít rozšíření !critsec . Zobrazí se stejná kolekce informací jako !ntsdexts.locks. Například:
0:000> !critsec 77fc49e0
CritSec ntdll!FastPebLock+0 at 77FC49E0
LockCount 0
RecursionCount 1
OwningThread c78
EntryCount 0
ContentionCount 0
*** Locked
Rozšíření !cs může zobrazit kritický oddíl na základě jeho adresy, vyhledat rozsah adres kritických oddílů a dokonce zobrazit trasování zásobníku přidružené ke každému kritickému oddílu. Některé z těchto funkcí vyžadují úplné symboly systému Windows, aby správně fungovaly. Pokud je aplikace Verifier aktivní, příkaz !cs -t může být použit k zobrazení stromu kritické sekce. Podrobnosti a příklady najdete na referenční stránce !cs .
Informace zobrazené souborem !cs se mírně liší od informací zobrazených pomocí !ntsdexts.locks a !critsec. Například:
## 0:000> !cs 77fc49e0
Critical section = 0x77fc49e0 (ntdll!FastPebLock+0x0)
DebugInfo = 0x77fc3e00
LOCKED
LockCount = 0x0
OwningThread = 0x00000c78
RecursionCount = 0x1
LockSemaphore = 0x0
SpinCount = 0x00000000
Příkaz dt (Display Type) lze použít k doslovnému zobrazení obsahu struktury RTL_CRITICAL_SECTION. Například:
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
Interpretace polí kritického oddílu v systémech Windows XP a Windows 2000
Nejdůležitější pole struktury kritického oddílu jsou následující:
V systému Microsoft Windows 2000 a Windows XP pole LockCount označuje počet, kolikrát jakékoli vlákno volal EnterCriticalSection rutinu pro tuto kritickou část, minus jeden. Pro odemknutou kritickou část toto pole začíná na -1. Každé volání EnterCriticalSection zvýší tuto hodnotu; každý volání LeaveCriticalSection ho sníží. Pokud je například LockCount 5, je tento kritický oddíl uzamčený, jedno vlákno ho získalo a pět dalších vláken čeká na tento zámek.
Pole RecursionCount označuje počet, kolikrát vlastnící vlákno nazývá EnterCriticalSection pro tuto kritickou část.
Pole EntryCount označuje, kolikrát vlákno jiné než vlastnící vlákno nazývá EnterCriticalSection pro tuto kritickou část.
Nově inicializovaný kritický oddíl vypadá takto:
0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount NOT LOCKED
RecursionCount 0
OwningThread 0
EntryCount 0
ContentionCount 0
Ladicí program zobrazí hodnotu "NOT LOCKED" pro LockCount. Skutečná hodnota tohoto pole pro odemknutou kritickou část je -1. Můžete to ověřit pomocí příkazu dt (Typ zobrazení):
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
Když první vlákno volá rutinu EnterCriticalSection, pole LockCount, RecursionCount, EntryCount a ContentionCount kritické sekce se všechna zvýší o jedna a OwningThread bude ID volajícího vlákna. EntryCount a ContentionCount se nikdy nezmenšují. Například:
0:000> !critsec 433e60
CritSec mymodule!cs+0 at 00433E60
LockCount 0
RecursionCount 1
OwningThread 4d0
EntryCount 0
ContentionCount 0
V tuto chvíli se můžou stát čtyři různé věci.
Vlastnící vlákno znovu volá EnterCriticalSection. Tím se zvýší LockCount a RecursionCount. EntryCount se nevýšil.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 2 OwningThread 4d0 EntryCount 0 ContentionCount 0
Jiné vlákno volá EnterCriticalSection. Tím se zvýší LockCount a EntryCount. RecursionCount se nevýšil.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount 1 RecursionCount 1 OwningThread 4d0 EntryCount 1 ContentionCount 1
Vlastnící vlákno volá LeaveCriticalSection. Tím se dekrementuje LockCount (na -1) a RecursionCount (na 0) a resetuje OwningThread na 0.
0:000> !critsec 433e60 CritSec mymodule!cs+0 at 00433E60 LockCount NOT LOCKED RecursionCount 0 OwningThread 0 EntryCount 0 ContentionCount 0
Další vlákno volá LeaveCriticalSection. Tím se dosáhne stejných výsledků jako při volání LeaveCriticalSection vlastnícím vláknem – dekrementuje LockCount (na -1) a RecursionCount (na 0) a resetuje OwningThread na 0.
Když některé programové vlákno volá LeaveCriticalSection, Windows snižuje LockCount a RecursionCount. Tato funkce má dobré i špatné aspekty. Umožňuje ovladači zařízení zadat kritický oddíl na jednom vlákně a ponechat kritický oddíl na jiném vlákně. Umožňuje však také omylem volat LeaveCriticalSection na nesprávném vlákně nebo volat LeaveCriticalSection příliš mnohokrát a způsobit LockCount dosažení hodnot nižších než -1. Tím dojde k poškození kritické sekce a způsobí, že všechna vlákna čekají na kritickou sekci neomezeně dlouho.
Interpretace polí kritického oddílu ve Windows Serveru 2003 SP1 a novějším
V systému Microsoft Windows Server 2003 Service Pack 1 a novějších verzích systému Windows se pole LockCount parsuje takto:
Nejnižší bit zobrazuje stav zámku. Pokud je tento bit 0, kritický oddíl je uzamčen; pokud je 1, kritická část není uzamčená.
Další bit ukazuje, zda bylo vlákno pro tento zámek probuzeno. Pokud je tento bit 0, bylo pro tento zámek probuzeno vlákno; pokud je 1, žádné vlákno nebylo probuzeno.
Zbývající bity jsou doplňkem počtu vláken čekajících na zámek.
Předpokládejme například, že LockCount je -22. Nejnižší bit lze takto určit:
0:009> ? 0x1 & (-0n22)
Evaluate expression: 0 = 00000000
Následující nejnižší bit lze určit tímto způsobem:
0:009> ? (0x2 & (-0n22)) >> 1
Evaluate expression: 1 = 00000001
Jedničkový doplněk zbývajících bitů je možné určit tímto způsobem:
0:009> ? ((-1) - (-0n22)) >> 2
Evaluate expression: 5 = 00000005
V tomto příkladu je první bit 0, a proto je kritický oddíl uzamčený. Druhý bit je 1, a proto nebylo pro tento zámek probuzeno žádné vlákno. Doplněk zbývajících bitů je 5, takže existuje pět vláken čekajících na tento zámek.
Další informace
Informace o tom, jak ladit vypršení časových limitů kritických oddílů, najdete v tématu Vypršení časových limitů kritických oddílů. Obecné informace o důležitých částech naleznete v sadě Microsoft Windows SDK, Windows Driver Kit (WDK) nebo Microsoft Windows Internals od Marka Russinovicha a Davida Solomona.