Compartir a través de


Mostrar una sección crítica

Las secciones críticas se pueden mostrar en modo de usuario mediante una variedad de métodos diferentes. El significado exacto de cada campo depende de la versión de Microsoft Windows que esté usando.

Mostrar secciones críticas

Las secciones críticas se pueden mostrar mediante la extensión !ntsdexts.locks, la extensión !critsec, la extensión !cs y el comando dt (Tipo de presentación).

La extensión !ntsdexts.locks muestra una lista de secciones críticas asociadas al proceso actual. Si se usa la opción -v , se muestran todas las secciones críticas. Este es un ejemplo:

0:000> !locks

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

....
Scanned 37 critical sections

Si conoce la dirección de la sección crítica que desea mostrar, puede usar la extensión !critsec . Esto muestra la misma colección de información que !ntsdexts.locks. Por ejemplo:

0:000> !critsec 77fc49e0

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

La extensión !cs puede mostrar una sección crítica en función de su dirección, buscar un intervalo de direcciones para las secciones críticas e incluso mostrar el seguimiento de la pila asociado a cada sección crítica. Algunas de estas características requieren símbolos completos de Windows para que funcionen correctamente. Si application Verifier está activo, !cs -t se puede usar para mostrar el árbol de sección crítico. Consulte la página de referencia de !cs para obtener más información y ejemplos.

La información mostrada por !cs es ligeramente diferente a la mostrada por !ntsdexts.locks y !critsec. Por ejemplo:

## 0:000> !cs 77fc49e0

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

El comando dt (Tipo de presentación) se puede usar para mostrar el contenido literal de la estructura RTL_CRITICAL_SECTION. Por ejemplo:

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

Interpretar campos de sección críticos en Windows XP y Windows 2000

Los campos más importantes de la estructura de sección crítica son los siguientes:

  • En Microsoft Windows 2000 y Windows XP, el campo LockCount indica el número de veces que cualquier subproceso ha llamado a la rutina EnterCriticalSection para esta sección crítica, menos una. Este campo comienza en -1 para una sección crítica desbloqueada. Cada llamada de EnterCriticalSection incrementa este valor; cada llamada de LeaveCriticalSection disminuye. Por ejemplo, si LockCount es 5, esta sección crítica está bloqueada, un subproceso lo ha adquirido y cinco subprocesos adicionales están esperando este bloqueo.

  • El campo RecursionCount indica el número de veces que el subproceso propietario ha llamado EnterCriticalSection para esta sección crítica.

  • El campo EntryCount indica el número de veces que un subproceso distinto del subproceso propietario ha llamado EnterCriticalSection para esta sección crítica.

Una sección crítica recién inicializada tiene este aspecto:

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

El depurador muestra "NOT LOCKED" como valor de LockCount. El valor real de este campo para una sección crítica desbloqueada es -1. Puede comprobarlo con el comando dt (Tipo de presentación):

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

Cuando el primer subproceso llama a la rutina EnterCriticalSection , los campos LockCount, RecursionCount, EntryCount y ContentionCount de la sección crítica se incrementan en uno y OwningThread se convierte en el identificador de subproceso del autor de la llamada. EntryCount y ContentionCount nunca se reducen. Por ejemplo:

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

En este momento, pueden ocurrir cuatro cosas diferentes.

  1. El subproceso propietario llama a EnterCriticalSection de nuevo. Esto incrementará LockCount y RecursionCount. EntryCount no se incrementa.

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          1
    RecursionCount     2
    OwningThread       4d0
    EntryCount         0
    ContentionCount    0
    
  2. Un subproceso diferente llama a EnterCriticalSection. Esto incrementará LockCount y EntryCount. RecursionCount no se incrementa.

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          1
    RecursionCount     1
    OwningThread       4d0
    EntryCount         1
    ContentionCount    1
    
  3. El subproceso propietario llama a LeaveCriticalSection. Esto disminuirá LockCount (a -1) y RecursionCount (a 0) y restablecerá OwningThread en 0.

    0:000> !critsec 433e60
    CritSec mymodule!cs+0 at 00433E60
    LockCount          NOT LOCKED 
    RecursionCount     0
    OwningThread       0
    EntryCount         0
    ContentionCount    0
    
  4. Otro subproceso llama a LeaveCriticalSection. Esto genera los mismos resultados que el subproceso propietario que llama a LeaveCriticalSection ; disminuirá LockCount (a -1) y RecursionCount (a 0) y restablecerá OwningThread a 0.

Cuando cualquier subproceso llama a LeaveCriticalSection, Windows disminuye LockCount y RecursionCount. Esta característica tiene aspectos buenos y malos. Permite que un controlador de dispositivo escriba una sección crítica en un subproceso y deje la sección crítica en otro subproceso. Sin embargo, también permite llamar accidentalmente a LeaveCriticalSection en el subproceso incorrecto o llamar a LeaveCriticalSection demasiadas veces y hacer que LockCount alcance valores inferiores a -1. Esto daña la sección crítica y hace que todos los subprocesos esperen indefinidamente en la sección crítica.

Interpretar campos de sección críticos en Windows Server 2003 SP1 y versiones posteriores

En Microsoft Windows Server 2003 Service Pack 1 y versiones posteriores de Windows, el campo LockCount se analiza de la siguiente manera:

  • El bit más bajo muestra el estado del bloqueo. Si este bit es 0, la sección crítica está bloqueada; si es 1, la sección crítica no está bloqueada.

  • El siguiente bit muestra si se ha despertado un subproceso para este bloqueo. Si este bit es 0, se ha despertado un subproceso para este bloqueo; si es 1, no se ha despertado ningún subproceso.

  • Los bits restantes son el complemento uno del número de subprocesos que esperan el bloqueo.

Por ejemplo, supongamos que LockCount es -22. El bit más bajo se puede determinar de esta manera:

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

El siguiente bit más bajo se puede determinar de esta manera:

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

El complemento uno de los bits restantes se puede determinar de esta manera:

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

En este ejemplo, el primer bit es 0 y, por tanto, la sección crítica está bloqueada. El segundo bit es 1, por lo que no se ha despertado ningún subproceso para este bloqueo. El complemento de los bits restantes es 5, por lo que hay cinco subprocesos esperando este bloqueo.

Información adicional

Para obtener información sobre cómo depurar tiempos de espera de sección críticos, consulte Tiempos de espera de sección críticos. Para obtener información general sobre las secciones críticas, consulta el Microsoft Windows SDK, el Kit de controladores de Windows (WDK) o Microsoft Windows Internals de Mark Russinovich y David Salomón.