Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ahogy a neve is sugallja, a mutex objektum egy olyan szinkronizálási mechanizmus, amelynek célja, hogy kölcsönösen kizárja a hozzáférést egyetlen erőforráshoz, amely a kernelmódú szálak egy készlete között van megosztva. Csak a legmagasabb szintű illesztőprogramok, például a vezető munkavégző szálakat használó fájlrendszer-illesztőprogramok (FSD-k) valószínűleg mutex objektumot használnak.
Lehetséges, hogy az illesztőprogram által létrehozott szálakkal vagy feldolgozói szálak visszahívási rutinjaival rendelkező legmagasabb szintű illesztőprogramok egy mutex objektumot használnak. A lapozható szálakkal vagy feldolgozószál-visszahívási rutinokkal rendelkező illesztőprogramoknak azonban nagyon óvatosan kell kezelnie a mutex-objektumok beszerzését, várakozását és kiadását.
A Mutex-objektumok beépített funkciókkal rendelkeznek, amelyek a rendszer (csak kernel módú) szálait kölcsönösen kizárják, holtpont nélküli hozzáférést biztosítanak az SMP-gépek megosztott erőforrásaihoz. A kernel egyszerre egyetlen szálhoz rendeli a mutex tulajdonjogát.
A mutex tulajdonjogának megszerzése megakadályozza a normál kernelmódú aszinkron eljáráshívások (APC-k) kézbesítését. A szálat nem szorítja ki egy APC, hacsak a kernel nem ad ki egy APC_LEVEL szintű szoftveres megszakítást egy speciális kernel APC futtatására, például az I/O-kezelő IRP-befejezési rutinjára, amely az eredményeket visszaadja az I/O-művelet eredeti kérelmezőjének.
A szálak megszerezhetik a már birtokolt mutex-objektumok tulajdonjogát (rekurzív tulajdonjog), de a rekurzívan beszerzett mutex-objektumok nem lesznek a Jeles állapotra állítva, amíg a szál teljesen fel nem adja a tulajdonjogát. Az ilyen szálnak explicit módon annyiszor kell feloldania a mutexet, ahányszor megszerezte annak tulajdonjogát, mielőtt egy másik szál megszerezhetné a mutexet.
A kernel soha nem engedi meg, hogy egy mutexet birtokló szál áttérjen a felhasználói módra anélkül, hogy először elengedné a mutexet, és azt Jelzett állapotba állítaná. Ha bármely olyan FSD által létrehozott vagy eszközvezérlő által létrehozott szál, amely egy mutex tulajdonosa, megpróbálja a mutex tulajdonjogának felszabadítása előtt visszaadni az irányítást az I/O-kezelőnek, a kernel leállítja a rendszert.
Minden mutex objektumot használó illesztőprogramnak egyszer meg kell hívnia KeInitializeMutex, mielőtt várakozik vagy felszabadítja a mutex objektumot. Az alábbi ábra bemutatja, hogyan használhat két rendszerszál egy mutex objektumot.
Ahogy az előző ábra is mutatja, a mutex objektumot használó illesztőprogramnak biztosítania kell a mutex objektum tárolását, amelynek rezidensnek kell lennie. Az illesztőprogram használhatja az illesztőprogram által létrehozott eszközobjektum eszközbővítményét, a vezérlőbővítményt, ha vezérlőobjektumothasznál, vagy a nem lapozott készletet, amelyet az illesztőprogram foglal le.
Amikor egy illesztő meghívja a KeInitializeMutex-t (általában a AddDevice rutinból), a meghajtónak egy mutatót kell átadnia a mutex objektum számára fenntartott tárolóhoz, amelyet a kernel jelzett állapotba inicializál.
Egy ilyen legmagasabb szintű illesztőprogram inicializálása után képes kezelni a megosztott erőforrásokhoz való kölcsönösen kizáró hozzáférést az előző ábrán látható módon. Az illesztőprogram küldési rutinjai például az eredendően szinkron műveletekhez és szálakhoz a mutexen keresztül védhetik az illesztőprogram által létrehozott várólistát az IRP-k számára.
Mivel KeInitializeMutexmindig Jelzett állapotra állítja a mutex objektum kezdeti állapotát (ahogy az előző ábrán is látható):
A diszpécser rutin kezdeti hívása a KeWaitForSingleObjectMutex mutatóval azonnal kész állapotba helyezi az aktuális szálat, megadja a szál tulajdonjogát a mutexnek, és alaphelyzetbe állítja a mutex állapotot a Not-Signaled értékre. Amint az ütemezési rutin újraindul, biztonságosan beilleszthet egy IRP-t a mutex által védett sorba.
Amikor egy második szál (egy másik kézbesítési rutin, az illesztőprogram által biztosított feldolgozói szál visszahívási rutinja vagy az illesztőprogram által létrehozott szál) meghívja KeWaitForSingleObject a Mutex mutatóval, a második szál várakozási állapotba kerül.
Amikor a kézbesítési rutin befejezi az IRP sorban állását az 1. lépésben leírtak szerint, meghívja KeReleaseMutex a Mutex mutatóval és egy logikai Várakozás értékkel, amely jelzi, hogy KeWaitForSingleObject (vagy KeWaitForMutexObject) hívását tervezi-e a Mutex, amint a KeReleaseMutex visszaadja az irányítást.
Feltéve, hogy a diszpécseri rutin a 3. lépésben felszabadította a mutex tulajdonjogát (VárakozásFALSEértékre van állítva), a mutex a KeReleaseMutex által jelzett állapotba kerül. A mutexnek jelenleg nincs tulajdonosa, ezért a kernel meghatározza, hogy egy másik szál vár-e a mutexre. Ha igen, a kernel a második szálat (lásd a 2. lépést) teszi a mutex tulajdonosává, valószínűleg a szál prioritását a legalacsonyabb valós idejű prioritási értékre emeli, és az állapotát készre változtatja.
A kernel azonnal ütemezi a második szál végrehajtását, amint elérhető egy processzor: vagyis amikor egyetlen másik, magasabb prioritású szál sincs készenléti állapotban, és nincsenek olyan kernel módú rutinok, amelyeket magasabb IRQL-en kellene futtatni. A második szál (egy IRP sorba állítását végző rutin, az illesztőprogram feldolgozó-szál visszahívási rutinja, vagy az illesztőprogram által létrehozott szál, amely egy IRP-t sorból kivesz) mostantól biztonságosan hozzáférhet az IRP-k mutex által védett sorához, amíg a KeReleaseMutexfüggvényt nem hívja.
Ha egy szál rekurzívan szerez tulajdonjogot egy mutex objektum fölött, akkor a szálnak annyiszor kell explicit módon meghívnia a KeReleaseMutex függvényt, ahányszor csak a mutexre várt, hogy a mutex objektumot a Jelzett állapotba állítsa. Ha például egy szál meghívja a KeWaitForSingleObject függvényt, majd a KeWaitForMutexObject függvényt ugyanazzal a Mutex mutatóval, akkor kétszer kell meghívnia a KeReleaseMutex függvényt, amikor megkapja a mutexet annak érdekében, hogy a mutex objektumot Jelzett állapotba állítsa.
A KeReleaseMutexWait paraméter TRUE értékre állítása azt jelzi, hogy a hívó azonnal meg kíván hívni egy KeWaitXxx támogatási rutint visszatérés után a KeReleaseMutex.
A Wait paraméter KeReleaseMutexre való beállításához tekintse meg az alábbi irányelveket:
Az IRQL PASSIVE_LEVEL-en futó lapozható szál vagy lapozható illesztő rutin soha nem hívhatja meg KeReleaseMutex a Várakozás paraméter értéke IGAZ. Az ilyen hívás végzetes oldalhibát okoz, ha a hívót véletlenül kiemelik a memóriából a KeReleaseMutex és KeWaitXxxObject(s) hívásai között.
A PASSIVE_LEVEL-nél nagyobb IRQL-en futó szokásos illesztőprogram-rutinok nem tudnak egy nem nulla időközre várakozni diszpécserobjektumokon anélkül, hogy ezzel ne okoznák a rendszer leállását. Azonban egy ilyen rutin meghívhatja a KeReleaseMutex függvényt, ha a mutex tulajdonosaként DISPATCH_LEVEL-nél kisebb vagy egyenlő IRQL-en fut.
A szabványos illesztőprogram-rutinok által futtatott IRQL-ek összegzését a Hardverprioritások kezelésecímű témakörben talál.