Nota
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare ad accedere o a cambiare directory.
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare a cambiare directory.
Come suggerisce il nome, un oggetto mutex è un meccanismo di sincronizzazione progettato per garantire l'accesso reciproco esclusivo a una singola risorsa condivisa tra un set di thread in modalità kernel. È probabile che solo i driver di livello più elevato, ad esempio i driver del file system (FSD) che usano thread di lavoro esecutivi, usino un oggetto mutex.
Possibilmente, un driver di livello più alto con thread creati dal driver o routine di callback del thread di lavoro potrebbe usare un oggetto mutex. Tuttavia, qualsiasi driver con thread di paginazione o routine di callback dei thread di lavoro deve gestire con molta attenzione le acquisizioni, le attese e i rilasci dei relativi oggetti mutex.
Gli oggetti Mutex hanno funzionalità predefinite che provvedono ai thread di sistema (solo in modalità kernel) un accesso mutuamente esclusivo e senza deadlock alle risorse condivise nelle macchine SMP. Il kernel assegna la proprietà di un mutex a un singolo thread alla volta.
L'acquisizione della proprietà di un mutex impedisce il recapito delle normali chiamate di routine asincrone in modalità kernel . Il thread non verrà preemptato da un APC a meno che il kernel non emetta un'interruzione software APC_LEVEL per eseguire uno specifico APC del kernel, come la routine di completamento IRP del gestore I/O che restituisce i risultati al richiedente originale di un'operazione di I/O.
Un thread può acquisire la proprietà di un oggetto mutex di cui è già proprietario (proprietà ricorsiva), ma un oggetto mutex acquisito in modo ricorsivo non è impostato nello stato Segnalato finché il thread non rilascia completamente la proprietà. Tale thread deve rilasciare in modo esplicito il mutex quante volte ha acquisito la proprietà prima che un altro thread possa acquisire il mutex.
Il kernel non consente mai a un thread proprietario di un mutex di eseguire una transizione alla modalità utente senza prima rilasciare il mutex e impostarlo sullo stato Segnalato. Se un thread creato da FSD o creato dal driver proprietario di un mutex tenta di restituire il controllo al gestore di I/O prima di rilasciare la proprietà del mutex, il kernel arresta il sistema.
Qualsiasi driver che usa un oggetto mutex deve chiamare KeInitializeMutex una volta prima che attenda o rilascia il relativo oggetto mutex. La figura seguente illustra come due thread di sistema potrebbero usare un oggetto mutex.
Come illustrato nella figura precedente, un driver che utilizza un oggetto mutex deve fornire lo spazio di archiviazione per l'oggetto mutex, che deve risiedere in memoria. Il driver può usare l'estensione del dispositivo di un oggetto dispositivo creato dal driver, l'estensione del controller se usa un oggetto controller o un pool non di pagine allocato dal driver.
Quando un driver chiama KeInitializeMutex (in genere dalla routine AddDevice ), deve passare un puntatore all'archivio del driver per l'oggetto mutex, che il kernel inizializza allo stato Signaled.
Dopo l'inizializzazione di un driver di livello massimo, può gestire l'accesso esclusivo a una risorsa condivisa, come illustrato nella figura precedente. Ad esempio, le routine di gestione degli invii di un driver per operazioni e thread intrinsecamente sincronizzati possono usare un mutex per proteggere una coda creata dal driver per i pacchetti di richiesta I/O.
Poiché KeInitializeMuteximposta sempre lo stato iniziale di un oggetto mutex su Signaled (come illustrato nella figura precedente):
La chiamata iniziale della routine dispatch a KeWaitForSingleObject con il puntatore Mutex inserisce immediatamente il thread corrente nello stato pronto, assegna alla proprietà del thread il mutex e reimposta lo stato del mutex su Not-Signaled. Non appena la routine dispatch riprende l'esecuzione, può inserire in modo sicuro un IRP nella coda protetta da mutex.
Quando un secondo thread (un'altra routine dispatch, routine di callback del thread di lavoro fornita dal driver o thread creato dal driver) chiama KeWaitForSingleObject con il puntatore Mutex , il secondo thread viene inserito nello stato di attesa.
Quando la routine dispatch termina l'accodamento dell'IRP come descritto nel passaggio 1, chiama KeReleaseMutex con il puntatore Mutex e un valore di attesa booleano, che indica se intende chiamare KeWaitForSingleObject (o KeWaitForMutexObject) con il Mutex non appena KeReleaseMutex restituisce il controllo.
Supponendo che la routine dispatch abbia rilasciato la proprietà del mutex nel passaggio 3 (Wait impostato su FALSE), il mutex viene impostato sullo stato Segnalato da KeReleaseMutex. Il mutex non ha attualmente alcun proprietario, quindi il kernel determina se un altro thread è in attesa di tale mutex. In tal caso, il kernel rende il secondo thread (vedere il passaggio 2) il proprietario del mutex, possibilmente aumenta la priorità del thread al valore di priorità in tempo reale più basso e ne modifica lo stato in pronto.
Il kernel invia il secondo thread per l'esecuzione non appena è disponibile un processore, ovvero quando nessun altro thread con priorità più alta è attualmente pronto e non sono presenti routine in modalità kernel da eseguire in un runtime di integrazione superiore. Il secondo thread (una routine dispatch che accoda un IRP o la routine di callback del thread di lavoro del driver o il thread creato dal driver che dequetta un IRP) può ora accedere in modo sicuro alla coda di runtime di integrazione protetta dal mutex fino a quando non chiama KeReleaseMutex.
Se un thread acquisisce la proprietà di un oggetto mutex in modo ricorsivo, tale thread deve chiamare esplicitamente KeReleaseMutex tante volte quante ha atteso sul mutex per impostare l'oggetto mutex nello stato Segnalato. Ad esempio, se un thread chiama KeWaitForSingleObject e quindi KeWaitForMutexObject con lo stesso puntatore Mutex , deve chiamare KeReleaseMutex due volte quando acquisisce il mutex per impostare l'oggetto mutex sullo stato Signaled.
La chiamata a KeReleaseMutex con il parametro Wait impostato su TRUE indica l'intenzione del chiamante di chiamare immediatamente una routine di supporto KeWaitXxx al ritorno da KeReleaseMutex.
Considerare le linee guida seguenti per impostare il parametro Wait su KeReleaseMutex:
Una routine del driver impaginabile o un thread impaginabile eseguito in IRQL PASSIVE_LEVEL non deve mai chiamare KeReleaseMutex con il parametro Wait impostato su TRUE. Tale chiamata causa un errore di pagina fatale se capita che il chiamante venga paginato fuori nell'intervallo tra le chiamate a KeReleaseMutex e KeWaitXxxObject.
Qualsiasi routine di driver standard eseguita a un IRQL maggiore di PASSIVE_LEVEL non può attendere un intervallo non zero su qualsiasi oggetto dispatcher senza arrestare il sistema. Tuttavia, tale routine può chiamare KeReleaseMutex se possiede il mutex mentre viene eseguita a un IRQL minore o uguale a DISPATCH_LEVEL.
Per un riepilogo dei livelli IRQL a cui vengono eseguite le routine dei driver standard, consultare Gestione delle priorità hardware.