Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Som namnet antyder är ett mutex-objekt en synkroniseringsmekanism som är utformad för att säkerställa ömsesidigt uteslutande åtkomst till en enda resurs som delas mellan en uppsättning trådar i kernelläge. Endast drivrutiner på högsta nivå, till exempel filsystemdrivrutiner (FSD) som använder executive worker-trådar, använder sannolikt ett mutex-objekt.
Möjligen kan en drivrutin på högsta nivå som har trådar skapade av drivrutinen eller arbetartråds-återanropsrutiner använda ett mutex-objekt. Men alla drivrutiner med sidhanterbara trådar eller återanropsrutiner för arbetartrådar måste hantera förvärv av, väntan på och frigörelse av sina mutex-objekt mycket noggrant.
Mutex-objekt har inbyggda funktioner som ger systemtrådar (endast kernelläge) ömsesidigt uteslutande, dödlägefri åtkomst till delade resurser på SMP-datorer. Kerneln tilldelar ägarskap för en mutex till en enskild tråd i taget.
Att skaffa ägarskap av en mutex förhindrar exekvering av vanliga asynkrona proceduranrop i kernelläge (APC). Tråden kommer inte att föregripas av en APC om inte kärnan utfärdar ett APC_LEVEL-programavbrott för att köra en speciell kärn-APC, till exempel I/O-hanterarens IRP-slutföranderutin som returnerar resultat till den ursprungliga beställaren av en I/O-operation.
En tråd kan skaffa ägarskap för ett mutex-objekt som den redan äger (rekursivt ägarskap), men ett rekursivt förvärvat mutex-objekt är inte inställt på tillståndet Signaled förrän tråden släpper ägarskapet helt. En sådan tråd måste uttryckligen släppa mutex så många gånger som den har erhållit ägarskap innan en annan tråd kan förvärva mutex.
Kerneln tillåter aldrig att en tråd som äger en mutex orsakar en övergång till användarläge utan att först släppa mutexen och ställa in den till tillståndet Signaled. Om någon FSD-skapad eller drivrutinsskapad tråd som äger en mutex försöker att lämna över kontrollen till I/O-hanteraren innan ägarskapet av mutex frigörs, så stänger kärnan ner systemet.
Alla drivrutiner som använder ett mutex-objekt måste anropa KeInitializeMutex en gång innan det väntar på eller släpper sitt mutex-objekt. Följande bild visar hur två systemtrådar kan använda ett mutex-objekt.
Som föregående bild visar måste en drivrutin som använder mutex-objekt tillhandahålla lagringen för mutex-objektet, som måste vara resident. Drivrutinen kan använda enhetstillägget för ett enhetsobjekt som skapats av drivrutinen, kontrollanttillägget om det använder ett kontrollantobjekt eller en icke-sidsidig pool som allokeras av drivrutinen.
När en drivrutin anropar KeInitializeMutex (vanligtvis från dess AddDevice-rutin ) måste den skicka en pekare till drivrutinslagringen för mutex-objektet, som kerneln initierar till tillståndet Signaled.
När en sådan drivrutin på högsta nivå har initierats kan den hantera ömsesidigt exklusiv åtkomst till en delad resurs enligt föregående bild. Till exempel kan en drivrutins dispatcher-rutiner för inneboende synkrona operationer och trådar använda en mutex för att skydda en drivrutinsskapad kö för IRP:er.
Eftersom KeInitializeMutexalltid anger det ursprungliga tillståndet för ett mutex-objekt till Signaled (som föregående bild visar):
En sändningsrutins första anrop till KeWaitForSingleObject med Mutex-pekaren placerar den aktuella tråden omedelbart i det klara tillståndet, ger trådägarskapet för mutex och återställer mutex-tillståndet till Not-Signaled. Så snart sändningsrutinen återupptas kan den på ett säkert sätt infoga en IRP i den mutexskyddade kön.
När en andra tråd (en annan sändningsrutin, av drivrutinen tillhandahållen återanropsrutin för arbetartråden, eller en av drivrutinen skapad tråd) anropar KeWaitForSingleObject med Mutex-pekaren, placeras den andra tråden i väntetillstånd.
När sändningsrutinen har slutfört köningen av IRP enligt beskrivningen i steg 1 anropar den KeReleaseMutex med Mutex-pekaren och ett booleskt väntevärde , vilket anger om den avser att anropa KeWaitForSingleObject (eller KeWaitForMutexObject) med Mutex så snart KeReleaseMutex returnerar kontrollen.
Förutsatt att sändningsrutinen släppte sitt ägarskap för mutexen i steg 3 (Vänta inställt på FALSE) ställs mutexen in i signalerat tillstånd av KeReleaseMutex. Mutex har för närvarande ingen ägare, så kärnan avgör om en annan tråd väntar på mutexen. I så fall gör kerneln den andra tråden (se steg 2) till mutex-ägare, vilket möjligen ökar trådens prioritet till det lägsta realtidsprioritetsvärdet och ändrar dess tillstånd till redo.
Kerneln skickar den andra tråden för körning så snart en processor är tillgänglig: det vill säga när ingen annan tråd med högre prioritet för närvarande är i klart tillstånd och det inte finns några kernellägesrutiner som ska köras vid en högre IRQL. Den andra tråden (en sändningsrutin som placerar en IRP i kö, eller drivrutinens arbetstråds-återanropsrutin, eller en av drivrutinen skapad tråd som tar ur kö en IRP) kan nu på ett säkert sätt komma åt den mutexskyddade kön med IRPer tills den anropar KeReleaseMutex.
Om en tråd får ägarskap för ett mutex-objekt rekursivt måste den tråden uttryckligen anropa KeReleaseMutex så många gånger som den väntade på mutex för att ställa in mutex-objektet till tillståndet Signaled. Om en tråd till exempel anropar KeWaitForSingleObject och sedan KeWaitForMutexObject med samma Mutex-pekare , måste den anropa KeReleaseMutex två gånger när det hämtar mutex för att ställa in mutex-objektet till tillståndet Signaled.
Att anropa KeReleaseMutex med parametern Wait inställd på TRUE anger anroparens avsikt att omedelbart anropa en KeWaitXxx-supportrutin vid retur från KeReleaseMutex.
Överväg följande riktlinjer för att ange parametern Wait till KeReleaseMutex:
En sidanpassad tråd eller sidanpassad drivrutinsrutin som körs på IRQL PASSIVE_LEVEL ska aldrig anropa KeReleaseMutex med parametern Wait inställd på TRUE. Ett sådant anrop orsakar ett allvarligt sidfel om anroparen råkar vara utspänd mellan anropen till KeReleaseMutex och KeWaitXxx-objekt.
Alla vanliga drivrutinsrutiner som körs på en IRQL som är större än PASSIVE_LEVEL kan inte vänta på ett icke-nollintervall på några dispatcher-objekt utan att ta ned systemet. En sådan rutin kan dock anropa KeReleaseMutex om den äger mutexen vid en IRQL som är mindre än eller lika med DISPATCH_LEVEL.
En sammanfattning av de IRQL:er där standarddrivrutinsrutiner körs finns i Hantera maskinvaruprioriteringar.