Sdílet prostřednictvím


Vytváření požadavků IOCTL v ovladačích

Ovladač třídy nebo jiný ovladač vyšší úrovně může přidělit IRP pro žádosti o řízení vstupně-výstupních operací a odeslat je následujícímu ovladači s nižší úrovní:

  1. Přidělení nebo opakované použití paketu IRP (IRP) s kódem hlavní funkce IRP_MJ_DEVICE_CONTROL nebo IRP_MJ_INTERNAL_DEVICE_CONTROL. Pomocí rutiny IoBuildDeviceIoControlRequest můžete konkrétně přidělit IOCTL IRP. Můžete také použít rutiny vytváření a inicializace protokolu IRP pro obecné účely, jako jsou IoAllocateIrp, IoReuseIrp nebo IoInitializeIrp. Další informace o přidělování IRP najdete v článku Vytváření IRP pro ovladače Lower-Level.

  2. Nastavte umístění vstupně-výstupního zásobníku nižšího ovladače pro IRP s kódem IOCTL_XXX a příslušnými parametry.

  3. Pokud se požadavek IOCTL dokončí asynchronně, zavolejte rutinu KeInitializeEvent , která inicializuje objekt události jako událost oznámení. Ovladač používá tuto událost k čekání na dokončení vstupně-výstupní operace.

  4. Volání IoSetCompletionRoutine s IRP tak, aby horní ovladač mohl v případě potřeby poskytnout rutinu IoCompletion pro vykonání následujícího:

    • Určete, jak nižší ovladač zpracoval danou žádost.

    • Znovu použijte IRP k odeslání další žádosti nebo zlikvidujte IRP vytvořené ovladačem po dokončení požadované operace nižším ovladačem. Ovladač nemůže znovu použít irps, které IoBuildDeviceIoControlRequest vytvořil. Další informace najdete v Opětovné použití IRPs.

  5. Zavolejte IoCallDriver a předejte žádost nižšímu ovladači.

  6. Pokud IoCallDriver vrátí STATUS_PENDING, zavolejte rutinu KeWaitForSingleObject , která aktuální vlákno umístí do stavu čekání. Ovladač nastaví parametr Object rutiny na adresu objektu události, který byl inicializován ve volání KeInitializeEvent.

    Poznámka Pokud ovladač volá KeWaitForSingleObject s parametrem časového limitu nastaveným na hodnotu NULL nebo na adresu proměnné, která obsahuje nenulovou hodnotu, musí ovladač běžet v IRQL <= APC_LEVEL v kontextu vlákna, který není nenulový. V opačném případě musí být ovladač spuštěn na úrovni IRQL <= DISPATCH_LEVEL.

Událost je signalována jeho rutinou IoCompletion při dokončení požadavku IOCTL. Jakmile je událost signalována, vlákno obnoví provádění.

Důležité Pokud ovladač přidělí objekt události jako místní proměnnou v zásobníku, ovladač musí volat KeWaitForSingleObject s parametrem WaitMode nastaveným na KernelMode. Tato hodnota parametru zabraňuje stránkování zásobníku.

Aby nedocházelo k problémům se synchronizací a možným narušením přístupu, parametry kódů řízení vstupně-výstupních operací zřídka zahrnují vložené ukazatele. S výjimkou určitých požadavků SCSI se vyrovnávací paměti v Irp->AssociatedIrp.SystemBuffer, v Irp->MdlAddress a v Parameters.DeviceIoControl.Type3InputBuffer v umístění zásobníku I/O operací ovladače neobsahují ukazatele na jiné vyrovnávací paměti dat, ani neobsahují struktury obsahující ukazatele pro systémem definované kódy řízení I/O operací. Další informace o tom, jak jsou vyrovnávací paměti dat používány s IRP, které obsahují řídicí kódy I/O, naleznete v tématu Popisy vyrovnávacích pamětí pro řídicí kódy I/O.

Nicméně dvojice ovladačů třídy/portu, které definují interní vstupně-výstupní řídicí kódy, může předat vložený ukazatel na paměť přidělenou ovladačem z ovladače vyšší úrovně na ovladač nižší úrovně. Za zajištění toho, aby byly splněny následující podmínky, je zodpovědný takový pár ovladačů třídy/portu:

  • K datům má přístup pouze jeden ovladač najednou.

  • Privátní vyrovnávací paměti dat jsou přístupné v libovolném kontextu vlákna ovladačem portu.

Ovladače zobrazení mohou volat funkci GDI EngDeviceIoControl k odesílání soukromě definovaných I/O požadavků specifických pro zařízení a také veřejných I/O požadavků definovaných systémem prostřednictvím ovladače systémového video portu dolů na odpovídající video miniport ovladače specifické pro adaptér.

Jakákoli komponenta uživatelského režimu balíčku ovladače může volat DeviceIoControl k odesílání vstupně-výstupních žádostí o řízení do ovladačového zásobníku. Správce vstupně-výstupních operací vytvoří požadavek IRP_MJ_DEVICE_CONTROL a doručí ho ovladači nejvyšší úrovně.