Condividi tramite


Oggetti semafori

Qualsiasi driver può usare un oggetto semaforo per sincronizzare le operazioni tra i thread creati dal driver e altre routine del driver. Ad esempio, un thread dedicato al driver potrebbe entrare in uno stato di attesa quando non sono presenti richieste di I/O in sospeso per il driver e le routine di invio del driver potrebbero impostare il semaforo sullo stato Segnalato subito dopo aver accodato un IRP.

Le routine dispatch dei driver di livello più elevato, che vengono eseguite nel contesto del thread che richiede un'operazione di I/O, possono usare un semaforo per proteggere una risorsa condivisa tra le routine dispatch. Le routine di invio dei driver di livello inferiore per le operazioni di I/O sincrone possono anche usare un semaforo per proteggere una risorsa condivisa tra quel subset di routine dispatch o con un thread creato dal driver.

Qualsiasi driver che usa un oggetto semaforo deve chiamare KeInitializeSemaphore prima di attendere o rilasciare il semaforo. La figura seguente illustra come un driver con un thread può usare un oggetto semaforo.

diagramma che illustra l'attesa di un oggetto semaforo.

Come illustrato nella figura precedente, tale driver deve fornire lo spazio di archiviazione per l'oggetto semaforo, che deve essere residente. 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 il driver AddDevice routine chiama KeInitializeSemaphore, deve passare un puntatore allo spazio di archiviazione residente del driver per l'oggetto semaforo. Inoltre, il chiamante deve specificare un Count per l'oggetto semaforo, come illustrato nella figura precedente, che ne determina lo stato iniziale (diverso da zero per Signaled).

Il chiamante deve inoltre specificare un Limite per il semaforo, che può essere uno dei seguenti:

  • limite = 1

    Quando questo semaforo è impostato sullo stato Signaled, un singolo thread in attesa dell'impostazione del semaforo sullo stato Signaled diventa idoneo per l'esecuzione e può accedere a qualsiasi risorsa protetta dal semaforo.

    Questo tipo di semaforo è detto anche semaforo binario perché un thread ha o non ha accesso esclusivo alla risorsa protetta dal semaforo.

  • limite > 1

    Quando questo semaforo è impostato sullo stato Segnalato, alcuni thread in attesa che l'oggetto semaforo sia impostato sullo stato Signaled diventi idoneo per l'esecuzione e possa accedere a qualsiasi risorsa protetta dal semaforo.

    Questo tipo di semaforo viene chiamato conteggio semaforo perché la routine che imposta il semaforo sullo stato Segnalato specifica anche il numero di thread in attesa che i thread in attesa vengano modificati dall'attesa alla preparazione. Il numero di thread in attesa di questo tipo può essere il limite impostato quando il semaforo è stato inizializzato o un numero minore di questo set di impostazioni Limite.

Pochi driver di dispositivo o intermedi hanno un singolo thread creato dal driver; anche meno hanno un set di thread che potrebbero attendere l'acquisizione o il rilascio di un semaforo. Pochi driver forniti dal sistema usano oggetti semafori e, di quelli che lo fanno, anche meno usano un semaforo binario. Anche se un semaforo binario potrebbe sembrare simile alla funzionalità di un oggetto mutex , un semaforo binario non fornisce la protezione predefinita contro i deadlock che un oggetto mutex ha per i thread di sistema in esecuzione nei computer SMP.

Dopo il caricamento di un driver con un semaforo inizializzato, può sincronizzare le operazioni sul semaforo che protegge una risorsa condivisa. Ad esempio, un driver con un thread dedicato al dispositivo che gestisce l'accodamento dei runtime di integrazione, ad esempio il driver del controller floppy di sistema, potrebbe sincronizzare l'accodamento IRP in un semaforo, come illustrato nella figura precedente:

  1. Il thread chiama KeWaitForSingleObject con un puntatore alla risorsa di archiviazione fornita dal driver per l'oggetto semaforo inizializzato per inserirlo in uno stato di attesa.

  2. I runtime di integrazione iniziano a venire in che richiedono operazioni di I/O del dispositivo. Le routine dispatch del driver inseriscono ogni IRP in una coda interlocked sotto il controllo spin-lock e chiamano KeReleaseSemaphore con un puntatore all'oggetto semaforo, un boost di priorità determinato dal driver per il thread (Incremento, come illustrato nella figura precedente), un Regolazione di 1 che viene aggiunto al conteggio del semaforo mentre ogni IRP viene accodato, e un Boolean Wait impostato su FALSE. Un semaforo diverso da zero Count imposta l'oggetto semaforo sullo stato Signaled, modificando così lo stato del thread in attesa su pronto.

  3. Il kernel invia il thread per l'esecuzione non appena è disponibile un processore, ovvero nessun altro thread con priorità più alta è attualmente nello stato pronto e non sono presenti routine in modalità kernel da eseguire in un runtime di integrazione superiore.

    Il thread rimuove un IRP dalla coda interlocked sotto il controllo spin-lock, lo passa ad altre routine del driver per un'ulteriore elaborazione e chiama di nuovo KeWaitForSingleObject. Se il semaforo è ancora impostato sullo stato Signaled (ovvero il conteggio rimane diverso da zero, a indicare che nella coda interlocked del driver sono presenti più IRP), il kernel modifica nuovamente lo stato del thread dall'attesa alla preparazione.

    Usando un semaforo di conteggio in questo modo, tale thread driver "sa" esiste un IRP da rimuovere dalla coda interlocked ogni volta che viene eseguito il thread.

Per informazioni specifiche per la gestione di IRQL quando si chiama KeReleaseSemaphore, vedere la sezione Osservazioni di KeReleaseSemaphore.

Qualsiasi routine del driver standard eseguita in un irQL maggiore di PASSIVE_LEVEL non può attendere un intervallo diverso da zero su qualsiasi oggetto dispatcher senza arrestare il sistema; per informazioni dettagliate , vedere oggetti Dispatcher kernel. Tuttavia, tale routine può chiamare KeReleaseSemaphore durante l'esecuzione in un IRQL minore o uguale a DISPATCH_LEVEL.

Per un riepilogo dei runtime di integrazione in cui vengono eseguite le routine dei driver standard, vedere Gestione delle priorità hardware. Per i requisiti IRQL di una routine di supporto specifica, vedere la pagina di riferimento della routine.