Sdílet prostřednictvím


Semaphore – objekty

Každý ovladač může k synchronizaci operací mezi vlákny vytvořenými ovladačem a dalšími rutinami ovladače použít objekt semaphore. Například vlákno vyhrazené ovladačem se může dostat do stavu čekání, když pro ovladač nejsou žádné nevyřízených vstupně-výstupní požadavky, a rutiny odesílání ovladače můžou nastavit semaphore na stav Signaled hned po jejich zařadí do fronty protokolu IRP.

Rutiny odesílání ovladačů nejvyšší úrovně, které se spouští v kontextu vlákna požadujícího vstupně-výstupní operaci, můžou k ochraně prostředku sdíleného mezi rutinami odesílání použít semafor. Rutiny odesílání ovladačů nižší úrovně pro synchronní vstupně-výstupní operace mohou také použít semafor k ochraně prostředku sdíleného mezi danou podmnožinou rutin dispečerských rutin nebo pomocí vlákna vytvořeného ovladačem.

Každý ovladač, který používá objekt semaphore, musí volat KeInitializeSemaphore, než počká nebo uvolní semaphore. Následující obrázek znázorňuje, jak může ovladač s vláknem použít objekt semaphore.

diagram znázorňující čekání na objekt semaphore

Jak ukazuje předchozí obrázek, musí takový ovladač poskytnout úložiště pro objekt semaphore, který by měl být rezidentní. Ovladač může použít rozšíření zařízení objektu zařízení vytvořeného ovladačem, rozšíření kontroleru, pokud používá objekt kontroleru nebo nestránkový fond přidělený ovladačem.

Když Rutina AddDevice ovladač volá KeInitializeSemaphore, musí předat ukazatel na rezidentní úložiště řidiče pro objekt semaphore. Kromě toho volající musí zadat Count pro objekt semaphore, jak je znázorněno na předchozím obrázku, který určuje jeho počáteční stav (nenulový pro signaled).

Volající také musí zadat Limit pro semafor, který může být následující:

  • limit = 1

    Pokud je tato semaphore nastavena na signalovaný stav, jedno vlákno, které čeká na nastavení semaphore na signalovaný stav, bude mít nárok na spuštění a může přistupovat k libovolnému prostředku chráněnému semaforem.

    Tento typ semaphore se také nazývá binární semaphore, protože vlákno má nebo nemá výhradní přístup k prostředku chráněnému semaphore.

  • Limit > 1

    Pokud je tento semaphore nastaven na signalovaný stav, určitý počet vláken čekajících na nastavení objektu semaphore na signalovaný stav se stane způsobilým ke spuštění a může získat přístup k libovolnému prostředku chráněnému semaforem.

    Tento typ semaforu se nazývá počítání semaforů, protože rutina, která nastaví semafor na signalovaný stav, určuje, kolik čekacích vláken může mít jejich stavy změněné od čekání na připraveno. Počet takových čekacích vláken může být Limit nastaven při inicializaci semaforu nebo některé číslo menší než toto přednastavení Limit.

Několik ovladačů zařízení nebo zprostředkujících ovladačů má jedno vlákno vytvořené ovladačem; ještě méně má sadu vláken, které by mohly čekat na získání nebo uvolnění semaforu. Několik systémově zadaných ovladačů používá objekty semaphore a z těch, které dělají, dokonce méně používají binární semafor. I když binární semaphore může vypadat podobně jako funkce objekt mutex, binární semaphore neposkytuje integrovanou ochranu proti zablokování, které objekt mutex má pro systémová vlákna spuštěná v počítačích SMP.

Po načtení ovladače s inicializovaným semaphorem může synchronizovat operace v semaforu, který chrání sdílený prostředek. Například ovladač s vláknem vyhrazeným zařízením, který spravuje řízení front ip adres, jako je ovladač disketové jednotky systému, může synchronizovat řízení front protokolu IRP v semaforu, jak je znázorněno na předchozím obrázku:

  1. Vlákno volá KeWaitForSingleObject s ukazatelem na úložiště dodaného ovladačem pro inicializovaný objekt semaphore, který se umístí do stavu čekání.

  2. IrPs začnou přicházet, které vyžadují vstupně-výstupní operace zařízení. Rutiny dispečerského ovladače vloží každý takový IRP do vzájemně zablokované fronty pod ovládací prvek spin-lock a volání KeReleaseSemaphore s ukazatelem na objekt semaphore, zvýšení priority určené řidičem pro vlákno (zvýšení, jak je znázorněno na předchozím obrázku), Úprava 1, která je přidána do semaphore Počet, protože každý IRP je zařazen do fronty, a logická hodnota Wait nastavena na hodnotu FALSE. Nenulový semaphore Count nastaví objekt semaphore na signalovaný stav, čímž změní stav čekající vlákna tak, aby byl připravený.

  3. Jádro odešle vlákno ke spuštění, jakmile bude k dispozici procesor: to znamená, že žádné jiné vlákno s vyšší prioritou není aktuálně ve stavu připraveno a neexistují žádné rutiny režimu jádra, které by se měly spouštět v prostředí IRQL vyšší.

    Vlákno odebere IRP z vzájemně zablokované fronty pod ovládacím prvku spin-lock, předá ho dalším rutinám ovladače pro další zpracování a volá KeWaitForSingleObject znovu. Pokud je semafor stále nastavený na stav Signaled (to znamená, že jeho počet zůstává nenulový, což znamená, že více přístupových bodů IRP jsou v vzájemně zablokované frontě ovladače), jádro znovu změní stav vlákna, aby čekal na připraveno.

    Při použití počítaného semaphore tímto způsobem je takové vlákno ovladače "ví", že existuje IRP, který se má odebrat z vzájemně zablokované fronty při každém spuštění vlákna.

Informace týkající se správy IRQL při volání KeReleaseSemaphorenaleznete v části Poznámky KeReleaseSemaphore.

Jakákoli standardní rutina ovladače, která běží v IRQL větší než PASSIVE_LEVEL nemůže čekat na nenulový interval na žádné objekty dispečera bez přenesení systému; Podrobnosti najdete v tématu objekty dispečeru jádra. Taková rutina však může volat KeReleaseSemaphore při spuštění v irQL menší nebo rovno DISPATCH_LEVEL.

Souhrn seznamů IRQLs, na kterých se spouští rutiny standardních ovladačů, najdete v tématu Správa priorit hardwaru. Požadavky IRQL konkrétní rutiny podpory najdete na referenční stránce rutiny.