Dela via


Snabba mutexar och skyddade mutexar

Från och med Windows 2000 kan drivrutiner använda snabba mutex om de kräver en form av ömsesidigt undantag med låg belastning för kod som körs på IRQL <= APC_LEVEL. En snabb mutex kan skydda en kodväg som bara måste anges av en tråd i taget. För att ange den skyddade kodsökvägen förvärvar tråden mutexen. Om en annan tråd redan har hämtat mutexen pausas den aktuella trådens exekvering tills mutexen släpps. För att avsluta den skyddade kodvägen släpper tråden mutex.

Från och med Windows Server 2003 kan drivrutiner också använda skyddade mutexar. Skyddade mutexar är ersättningar som kan direkt användas för snabbmutexar men ger bättre prestanda. Precis som en snabb mutex kan en skyddad mutex skydda en kodsektion som bara måste nås av en tråd i taget. Men kod som använder skyddade mutexs körs snabbare än kod som använder snabba mutexar.

I versioner av Windows före Windows 8 implementeras skyddade mutexes på ett annat sätt än snabba mutexar. En kodsökväg som skyddas av en snabb mutex körs på nivån IRQL = APC_LEVEL. En kodsökväg som skyddas av en skyddad mutex körs på IRQL <= APC_LEVEL men med alla APC:er inaktiverade. I dessa tidigare versioner av Windows är förvärvandet av en skyddad mutex en snabbare process än förvärvandet av en snabb mutex. Dessa två typer av mutex fungerar dock identiskt och omfattas av samma begränsningar. I synnerhet bör kärnrutiner som är förbjudet att anropa på IRQL = APC_LEVEL inte anropas från en kodväg som skyddas av antingen en snabb mutex eller en skyddad mutex.

Från och med Windows 8 implementeras skyddade mutexes som snabba mutexes. I en kodsökväg som skyddas av ett skyddat mutex eller en snabb mutex behandlar drivrutinsverifieraren anrop till kernelrutiner som inträffar vid IRQL = APC_LEVEL. Precis som i tidigare versioner av Windows är anrop som är olagliga på APC_LEVEL olagliga i en kodsökväg som skyddas av en skyddad mutex eller en snabb mutex.

Snabbmutexar

En snabb mutex representeras av en FAST_MUTEX struktur. Drivrutinen allokerar sin egen lagring för en FAST_MUTEX struktur och anropar sedan rutinen ExInitializeFastMutex för att initiera strukturen.

En tråd förvärvar en snabb mutex genom att göra något av följande:

  • Anropa ExAcquireFastMutex-rutinen. Om mutexen redan har hämtats av en annan tråd, pausas körningen av den anropande tråden tills mutexen blir tillgänglig.

  • Anropa rutinen ExTryToAcquireFastMutex för att försöka hämta den snabba mutexen utan att pausa den aktuella tråden. Rutinen returnerar omedelbart, oberoende av om mutexen har förvärvats. ExTryToAcquireFastMutex returnerar TRUE om det lyckades hämta mutex för anroparen. annars returneras FALSE.

En tråd anropar ExReleaseFastMutex för att släppa en snabb mutex som har hämtats av antingen ExAcquireFastMutex eller ExTryToAcquireFastMutex.

En kodväg som skyddas av en snabb mutex körs på IRQL = APC_LEVEL. ExAcquireFastMutex och ExTryToAcquireFastMutex höjer den aktuella IRQL:n till APC_LEVEL och ExReleaseFastMutex återställer den ursprungliga IRQL:n. Därför inaktiveras alla APC:er medan tråden innehar en snabb mutex.

Om en kodsökväg garanterat alltid körs på APC_LEVEL kan drivrutinen i stället anropa ExAcquireFastMutexUnsafe och ExReleaseFastMutexUnsafe för att hämta och släppa en snabb mutex. Dessa rutiner ändrar inte aktuell IRQL och kan endast användas på ett säkert sätt när den aktuella IRQL:en är APC_LEVEL.

Snabba mutexar kan inte hämtas rekursivt. Om en tråd som redan har en snabb mutex försöker hämta den, kommer den tråden att fastna i ett dödläge. Snabba mutexer kan endast användas i kod som körs på IRQL <= APC_LEVEL.

Skyddade låsmekanismer

Skyddade mutexes, som är tillgängliga från och med Windows Server 2003, utför samma funktion som snabba mutexar men med högre prestanda.

Från och med Windows 8 implementeras skyddade mutexar och snabba mutexer på samma sätt.

I versioner av Windows före Windows 8 implementeras skyddade mutexes på ett annat sätt än snabba mutexar. Om du hämtar en snabb mutex genereras den aktuella IRQL till APC_LEVEL, samtidigt som en skyddad mutex hämtas till en skyddad region, vilket är en snabbare åtgärd. Mer information om skyddade regioner finns i Kritiska regioner och skyddade regioner.

En skyddad mutex representeras av en KGUARDED_MUTEX struktur. Drivrutinen allokerar sin egen lagring för en KGUARDED_MUTEX struktur och anropar sedan rutinen KeInitializeGuardedMutex för att initiera strukturen.

En tråd förvärvar en skyddad mutex på något av följande sätt:

  • Anropar KeAcquireGuardedMutex. Om mutexen redan har hämtats av en annan tråd, pausas körningen av den anropande tråden tills mutexen blir tillgänglig.

  • Anropar KeTryToAcquireGuardedMutex för att försöka hämta den skyddade mutexen utan att pausa den aktuella tråden. Rutinen returnerar omedelbart, oberoende av om mutexen har förvärvats. KeTryToAcquireGuardedMutex returnerar TRUE om det lyckades hämta mutex för anroparen. annars returneras FALSE.

En tråd anropar KeReleaseGuardedMutex för att släppa en skyddad mutex som erhållits av antingen KeAcquireGuardedMutex eller KeTryToAcquireGuardedMutex.

En tråd som innehåller en skyddad mutex körs implicit i en skyddad region. KeAcquireGuardedMutex och KeTryToAcquireGuardedMutex går in i den skyddade regionen, medan KeReleaseGuardedMutex avslutar den. Alla APC:er inaktiveras medan tråden innehåller en skyddad mutex.

Om en kodsökväg garanterat körs med alla APC:er inaktiverade kan drivrutinen i stället använda KeAcquireGuardedMutexUnsafe och KeReleaseGuardedMutexUnsafe för att hämta och släppa den skyddade mutexen. Dessa rutiner går inte in i eller ut ur en skyddad region och kan endast användas i en redan befintlig skyddad region eller i IRQL = APC_LEVEL.

Skyddade mutexes kan inte hämtas rekursivt. Om en tråd som redan håller i en skyddad mutex försöker hämta den, kommer den tråden att blockeras. Skyddade mutexes kan endast användas i kod som körs på IRQL <= APC_LEVEL.