Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Pracovní položka je úkol, který ovladač provádí ve funkci zpětného volání události EvtWorkItem. Tyto funkce běží asynchronně v IRQL = PASSIVE_LEVEL v kontextu systémového pracovního vlákna.
Ovladače založené na rámci běžně používají pracovní položky, když funkce EvtInterruptDpc nebo EvtDpcFunc, která běží na úrovni IRQL = DISPATCH_LEVEL, musí provádět další zpracování na úrovni IRQL = PASSIVE_LEVEL.
Jinými slovy, ovladač může použít pracovní položky, pokud funkce, která běží v IRQL = DISPATCH_LEVEL musí volat funkci, která se dá volat pouze v IRQL = PASSIVE_LEVEL.
Typicky zpětné volání ovladače, jako je EvtInterruptDpc nebo EvtDpcFunc, vytvoří objekt pracovní položky a přidá jej do fronty pracovních položek systému. Následně systémové pracovní vlákno vyjme z fronty objekt a volá funkci zpětného volání pracovního položky EvtWorkItem.
Ukázkové ovladače, které používají pracovní položky
Ukázkové ovladače založené na frameworku, které používají pracovní položky, zahrnují 1394, AMCC5933, PCIDRV a Toaster.
Nastavení pracovní položky
Pokud chcete nastavit pracovní položku, musí ovladač:
Vytvořte pracovní položku.
Ovladač volá WdfWorkItemCreate pro vytvoření objektu pracovní položky a určení funkce zpětného volání EvtWorkItem, která bude zpracovávat pracovní položku.
Uložte informace o pracovní položce.
Ovladače obvykle používají kontextovou paměť objektu pracovní položky k ukládání informací o úloze, kterou by měla provést funkce EvtWorkItem zpětné volání. Když je volána zpětná volací funkce EvtWorkItem, může načíst informace přístupem k této kontextové paměti. Informace o přidělování paměti kontextu a přístupu k němu naleznete v tématu Framework Object Context Space.
Přidejte pracovní položku do fronty pracovních položek systému.
Ovladač volá WdfWorkItemEnqueue, který přidá pracovní položku ovladače do fronty pracovních položek.
Když ovladač volá WdfWorkItemCreate, musí zadat popisovač buď k objektu zařízení frameworku, nebo k objektu fronty frameworku. Když systém odstraní tento objekt, odstraní také všechny existující pracovní položky, které jsou přidruženy k objektu. Objekt pracovní položky bude zlikvidován a jeho přidružené zpětné volání bude vyčištěno před vyvoláním zpětného volání nadřazeného objektu EvtCleanupCallback.
Další informace o pravidlech čištění pro hierarchii objektů architektury naleznete v tématu Framework Object Life Cycle.
Použití funkce zpětného volání Work-Item
Po přidání pracovní položky do fronty zůstane ve frontě, dokud není k dispozici systémové pracovní vlákno. Pracovní vlákno systému odebere pracovní položku z fronty a poté zavolá funkci zpětného volání EvtWorkItem a odešle objekt pracovní položky jako vstup.
Funkce zpětného volání EvtWorkItem obvykle provádí následující kroky:
Získá informace o pracovní položce zadaných ovladačem tak, že přistupuje k kontextové paměti objektu pracovní položky.
Provede zadaný úkol. V případě potřeby může funkce zpětného volání volat WdfWorkItemGetParentObject, aby určila nadřazený objekt pracovní položky.
Volá WdfObjectDelete k odstranění objektu pracovní položky nebo, pokud ovladač znovu vytvoří frontu pracovní položky, znamená, že popisovač pracovní položky je nyní k dispozici pro opakované použití.
Úloha, kterou provádí funkce zpětného volání každé pracovní položky, musí být poměrně krátká. Operační systém poskytuje omezený počet systémových pracovních vláken, takže ovladač může bránit výkonu systému, pokud k provádění časově náročných úloh používá funkce zpětného volání pracovních položek.
vytváření a odstraňování pracovních položek
Ovladače můžou k vytváření a odstraňování pracovních položek používat jednu z následujících dvou technik:
Každou pracovní položku použijte jednou: vytvořte pracovní položku, když ji potřebujete, a odstraňte ji ihned po jejím použití.
Tato technika je užitečná pro ovladače, které vyžadují občasné použití (méně často než jednou za minutu) malého počtu pracovních položek.
Například funkce zpětného volání EvtInterruptDpc ovladače může volat WdfWorkItemCreate a pak WdfWorkItemEnqueue, a funkce zpětného volání EvtWorkItem pracovní položky může volat WdfObjectDelete.
Pokud váš ovladač postupuje podle tohoto scénáře a pokud jeho EvtInterruptDpc zpětné volání obdrží STATUS_INSUFFICIENT_RESOURCES návratovou hodnotu z WdfWorkItemCreate, ovladač musí být schopný odložit požadovanou práci, dokud nebudou dostupné systémové prostředky (obvykle paměť).
Vytvořte jednu nebo více pracovních položek, které ovladač podle potřeby znovu zařazuje.
Tato technika je užitečná pro ovladače, které často používají pracovní položky (častěji než jednou za minutu), nebo pokud zpětné volání funkce EvtInterruptDpc nemůže snadno zpracovat návratovou hodnotu STATUS_INSUFFICIENT_RESOURCES z WdfWorkItemCreate.
Systém nepřiděluje pracovní vlákno pracovní položce, dokud ovladač nevolá WdfWorkItemEnqueue. Proto i když jsou pracovní vlákna systému omezeným prostředkem, vytváření pracovních položek při inicializaci zařízení spotřebovává malé množství paměti, ale jinak nemá vliv na výkon systému.
Následující kroky popisují možný scénář:
- Funkce zpětného volání ovladače EvtDriverDeviceAdd volá WdfWorkItemCreate, aby získala popisovač pracovní položky.
- Funkce zpětného volání EvtInterruptDpc vytvoří seznam akcí, které musí provést funkce zpětného volání EvtWorkItem, a poté pomocí popisovače z kroku 1 volá WdfWorkItemEnqueue.
- Funkce zpětného volání ovladače EvtWorkItem provede seznam akcí a nastaví příznak, který označuje, že tato funkce byla spuštěna.
Následně se pokaždé, když je volána funkce zpětného volání EvtInterruptDpc, musí určit, zda byla funkce zpětného volání EvtWorkItem již spuštěna. Pokud nebyla spuštěna funkce zpětného volání EvtWorkItem, funkce zpětného volání EvtInterruptDpc nevolá WdfWorkItemEnqueue, protože pracovní položka je stále zařazena do fronty. V tomto případě funkce zpětného volání EvtInterruptDpc pouze aktualizuje seznam akcí pro funkci zpětného volání EvtWorkItem.
Každá pracovní položka je přidružená k zařízení nebo frontě. Když je odebráno přidružené zařízení nebo fronta, framework odstraní všechny přidružené pracovní položky, takže pokud používáte tuto techniku, ovladač nemusí volat WdfObjectDelete.
Několik ovladačů může vyžadovat volání WdfWorkItemFlush pro vyprázdnění pracovních položek z fronty pracovních položek. Příklad použití WdfWorkItemFlush, viz referenční stránka metody.
Pokud ovladač volá WdfObjectDelete u nevyřízené pracovní položky, výsledek závisí na stavu pracovní položky:
| Stav pracovní položky | Výsledek |
|---|---|
| Vytvořeno, ale nezařazeno do fronty | Pracovní položka bude okamžitě uklizena. |
| Enqueued | Volání WdfObjectDelete počká, až se dokončí provádění pracovní položky, a poté se pracovní položka odstraní. |
| Provádění | Pokud ovladač volá WdfObjectDelete z toho EvtWorkItem (ve stejném vlákně), WdfObjectDelete se vrátí okamžitě. Po dokončení EvtWorkItem bude pracovní položka vyčištěna. Jinak WdfObjectDelete čeká na dokončení EvtWorkItem. |