IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Špecifiká vývoja ovládačov 3

V minulom dieli Špecifiká vývoja ovládačov 2 sme sa zamerali na pamäť. V tomto diele miniseriálu o rôznych aspektoch vývoja ovládačov sa budeme zaoberať len jedným témou, ktoré prestupuje celým jadrom a každý vývojár ovládačov by s ním mal byť dobre oboznámený. Ide o mechanizmus hardvérových priorít.

Na rozdiel od plánovacie priority vlákien (a poťažmo procesov), hardvérová priorita vlákna neudáva, ako často mu bude pridelený procesor, ale aké úkony môže vykonávať. Pritom platí, že kód bežiaci s hardvérovou prioritou X môže byť prerušený (Preplánovanie) iba kódom s hardvérovou prioritou Y> X. Čím vyššia hardvérovú prioritou vlákno disponuje, tým menej vecí môže vykonávať, ale tým menšie množstvo udalostí môže prerušiť jeho beh. Termín hardvérová priorita je mnou vymyslený slovenský ekvivalent súslovie interrupt request level (IRQL), ktorá sa používa v dokumentácii.

Existuje 32 rôznych hardvérových priorít pre 32-bitový a 16 pre 64-Windows. Najdôležitejšie hodnoty sú 0 (PASSIVE_LEVEL), 1 (APC_LEVEL), 2 (DISPATCH_LEVEL) a 31 (resp. 15) (HIGH_LEVEL). Tabuľka 1 popisuje aké obmedzenia tieto priority kladú na vykonávaný kód.

Tabuľka 1: Prehľad najdôležitejších IRQL a ich obmedzenia

PASSIVE_LEVEL APC_LEVEL DISPATCH_LEVEL HIGH_LEVEL
pasívne čakanie ÁNO ÁNO NIE NIE
aktívne čakania ÁNO ÁNO ÁNO ÁNO
stránkovanie ÁNO ÁNO NIE NIE
alokácia pamäte ÁNO ÁNO ÁNO * NIE
API ÁNO NIE NIE NIE
Vlákno pasívne čaká, pokiaľ nie je naplánované na procesore a zároveň pre jeho možný beh je potrebné splniť nejakú ďalšiu podmienku, napríklad dokončiť čítanie dát z disku. Pasívne čakanie je nutnou podmienkou pre takmer všetky neinformatizovanom činnosti a samozrejme pre samotný plánovač vlákien. Jeho nedostupnosť od DISPATCH_LEVEL vyššie veľmi obmedzuje možnosti, ktoré vývojár ovládače na danej hardvérovej priorite má.

Pri Aktívnym čakaní vlákno beží na procesore a neustále testuje, či je určitá podmienka splnená či stále ešte nie. Keďže tento druh čakania nevyžaduje žiadnu podporu od operačného systému, je možné ho vykonávať na ľubovoľnej IRQL.

Ako bolo povedané v minulom dieli, stránkovanie môže byť systémom odložená na disk a odtiaľ načítaná až v okamihu potreby. Keďže pre takýto úkon je potreba na načítanie dát (pasívne) počkať, ku stránkovanie nemožno pristupovať a ani ju (de) alokovať na IRQL> = DISPATCH_LEVEL.

Do oblasti nestránkovej pamäti (prípadne stránkovanie, ktoré bolo zakázané odobrať sa na disk) je možné pristupovať na ľubovoľné HW priorite. Jediné obmedzenie platí pre jej (de) alokáciu, tieto činnosti je nutné vykonávať maximálne na APC_LEVEL (DISPATCH_LEVEL pre nestránkovú).

Na úrovni DISPATCH_LEVEL je vykonávaná väčšina rutín plánovača. Vďaka tomu je možné napríklad preplánovať vlákno bežiaci na PASSIVE_LEVEL iným vláknom na rovnakej hardvérovej priorite, hoci to poučka uvedená vyššie zdanlivo zakazuje. Trik spočíva v tom, že plánovač IRQL zvýši na DISPATCH_LEVEL, vykoná vlastné preplánovanie a následne ju zníži na úroveň novo naplánovaného vlákna. Dočasné zvýšenie IRQL patrí medzi legitímne kroky, nedochádza teda k porušeniu žiadneho jadrového zákona.

Obrázok nižšie ilustruje stav opísaný v predchádzajúcom odseku. Na procesora najprv beží vlákno A na IRQL APC_LEVEL. Po určitej dobe plánovač usúdi, že nastal čas na zmenu; IRQL sa zvýši na DISPATCH_LEVEL a dôjde k naplánovanie vlákna B. Plánovač potom svoju intervenciu ukončí a nechá bežať vlákno B. IRQL klesne na poslednú známu hodnotu pre vlákno B, čo je v tomto prípade PASSIVE_LEVEL. Vďaka dočasnému zvýšeniu na DISPATCH_LEVEL nedošlo k porušeniu žiadneho jadrového pravidla.

Zdanlivé porušenie pravidla o hardvérových prioritách - Pokročilé postupy pre Windows

Z predchádzajúceho odseku tiež vyplýva, že ak vlákno zdvihne HW prioritu nad APC_LEVEL, nemôže ho z aktuálneho procesora nikto "vyštípat". Môže byť krátkodobo prerušené inými udalosťami nastávajúcimi na vyšších IRQL (hardvérová prerušenia, časovač, meziprocesorová komunikácie ...), tie ho ale nemôžu preplánovať. Z tohto dôvodu na vyšších IRQL nedáva príliš zmysel hovoriť o vláknach, ale len o procesoroch.

Vzhľadom k vyššie popísaným obmedzením je cieľom každého ovládača vykonávať maximum kódu na IRQL PASSIVE_LEVEL (prinajhoršom na APC_LEVEL). Pre zostúpení z vyšších IRQL na nižšiu existujú dokumentované postupy, ktorý spočívajú v tom, že ovládač naplánuje operáciu, ktorú potrebuje vykonať na nízkej IRQL, na neskoršiu dobu a vráti riadenie jadru systému. Na vykonanie operácie nemôže počkať, neb služby plánovača nie sú na vyšších IRQL dostupné. Tieto mechanizmy sa nazývajú odložené volanie procedúry a pracovné vlákna.

Odložené volanie procedúry (Deferred Procedure Call - DPC) slúži k zníženiu hodnoty IRQL na DISPATCH_LEVEL. Najčastejšie použitie nájdeme v obslužných rutinách prerušenia. Napríklad stlačenie klávesu na notebookové klávesnici vyvolá hardvérové prerušenia, ktoré spracováva ovládač i8042prt.sys. Jeho obslužná rutina je, ako to u prerušenie býva, volaná na IRQL> DISPATCH_LEVEL, a tak sú jej možnosti veľmi obmedzené. Ovládač teda iba zistí, k akej udalosti klávesnice došlo (vrátane toho, aká klávesa bola stlačená) a požiada systém, aby, až IRQL dostatočne klesne, zavolal určitú funkciu a odovzdal jej zistené informácie v parametroch. Tým vlastne odloží spracovanie informácií na vhodnejšie obdobie. Bezpochyby nie je bez zaujímavosti, že si ovládač môže vybrať procesor, na ktorom má byť odložená procedúra vykonaná.

Ak pri spracovaní informácií ovládač usúdi, že úroveň DISPATCH_LEVEL je pre neho stále príliš vysoká, môže požiadať o pomoc niektorej z tzv. Pracovných vlákien (worker threads) - množiny vlákien bežiacich na IRQL PASSIVE_LEVEL a vykonávajúcich prácu, ktorú im zadá ľubovoľná komponenta jadra. Práca v tomto prípade znamená volanie funkcie so zadaným parametrom. Mechanizmus je teda navonok značne podobný DPC. Akonáhle sa ovládač dostane na PASSIVE_LEVEL, môže napríklad vykonávať zápisy do registra či do súboru, čo sú operácie na vyšších IRQL zakázané.

Systém sa ovládače pre vykonávanie maxima kódu na nízkych IRQL snaží donútiť aj tým, že obmedzuje časový interval, ktorý možno na vyšších úrovniach stráviť. Pokiaľ ho ovládač prekročí, dochádza k modrej obrazovke smrti. Vzhľadom na to, že ovládače sú vlastne DLL knižnice, ktoré systém zavolá, keď je potreba, splnenie tejto požiadavky zvyčajne nepredstavuje veľký problém - ovládač urobí, čo musí, a v prípade potreby použije mechanizmus pre zníženie IRQL a odovzdá konania späť volajúcemu.

Časový limit pre beh kódu na IRQL> = DISPATCH_LEVEL má svoj význam, pretože na procesoroch s týmto IRQL nefunguje plánovač, čo narušuje ilúziu súčasného vykonávanie mnohých úloh.


 

Všetky články v sekcii
Pokročilé postupy pre Windows
Článok pre vás napísal Martin Dráb
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje studiu obecné teorie operačních systémů, vnitřnímu uspořádání jádra OS Windows, trochu také matematice a šifrování
Aktivity