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.
Následující faktory komplikují kód ovladače, který zpracovává přerušení hardwaru v multiprocesorových systémech:
Pokaždé, když zařízení přeruší, poskytuje informace specifické pro přerušení, které jsou nestálé, protože je možné je přepsat při příštím přerušení zařízení.
Zařízení přerušují na relativně vysokých úrovních IRQL a jejich rutiny obsluhy přerušení (ISRs) mohou přerušit provádění jiného kódu ovladače.
V případě přerušení DIRQL musí ISR běžet na úrovni DIRQL, přičemž drží spinlock dodaný ovladačem, aby zabránil dalším přerušením při ukládání volatilních dat. DIRQL zabraňuje přerušení aktuálním procesorem a spinlock brání přerušení jiným procesorem.
IsR musí běžet rychle, protože zařízení nemůže přerušit během provádění isR. Dlouhé doby provádění ISR můžou systém zpomalit nebo způsobit ztrátu dat.
Rutina ISR i odloženého volání procedury (DPC) obvykle musí přistupovat k paměťové oblasti, ve které ISR ukládá nestálá data zařízení. Tyto rutiny se musí vzájemně synchronizovat, aby neměly přístup k oblasti úložiště ve stejnou dobu.
Vzhledem ke všem těmto faktorům musíte při psaní kódu ovladače, který zpracovává přerušení, použít následující pravidla:
Pouze funkce zpětného volání EvtInterruptIsr přistupuje k nestálým datům z přerušení, jako jsou například registry zařízení obsahující informace o přerušení.
Funkce zpětného volání EvtInterruptIsr by měla přesunout nestálá data do paměťového bufferu pro data přerušení, který je definován ovladačem, a ke kterému může přistupovat funkce zpětného volání EvtInterruptDpc, funkce zpětného volání EvtInterruptWorkItem, nebo více funkcí zpětného volání EvtDpcFunc.
Pokud váš ovladač poskytuje funkce zpětného volání EvtInterruptDpc nebo EvtInterruptWorkItem pro objekty přerušení, nejlepším místem pro uložení dat přerušení je kontextový prostor objektu přerušení. Pomocí popisovače objektu, který obdrží, mají funkce zpětného volání objektu přerušení přístup ke kontextovému prostoru objektu.
Pokud váš ovladač poskytuje více funkcí zpětného volání EvtDpcFunc pro každou funkci zpětného volání EvtInterruptIsr , můžete ukládat přerušená data v kontextu každého objektu DPC.
Veškerý kód ovladače, který přistupuje k vyrovnávací paměti dat přerušení, musí být synchronizován tak, aby k datům současně přistupovala jen jedna rutina.
V případě objektů přerušení DIRQL přistupuje funkce zpětného volání EvtInterruptIsr k této vyrovnávací paměti dat na úrovni IRQL = DIRQL, zatímco drží zámek poskytnutý ovladačem. Proto všechny rutiny, které přistupují k vyrovnávací paměti, musí také běžet na úrovni DIRQL při držení spinlocku. (Funkce zpětného volání EvtInterruptDpc nebo EvtDpcFunc přerušení je obvykle jedinou jinou rutinou, která musí přistupovat k vyrovnávací paměti.)
Všechny rutiny, které přistupují k vyrovnávací paměti dat přerušení, s výjimkou funkce zpětného volání EvtInterruptIsr, musí provést jednu z těchto věcí:
- Zavolejte WdfInterruptSynchronize pro naplánování funkce zpětného volání EvtInterruptSynchronize, která přistupuje k vyrovnávací paměti dat přerušení.
- Umístěte kód, který přistupuje k vyrovnávací paměti pro přerušení dat mezi voláními WdfInterruptAcquireLock a WdfInterruptReleaseLock.
Obě tyto techniky umožňují funkci EvtInterruptDpc nebo EvtDpcFunc přistupovat k datům přerušení na DIRQL při podržení spinového zámku přerušení. DIRQL zabraňuje přerušení aktuálního procesoru a spinlock brání přerušení jiným procesorem.
Pokud vaše zařízení podporuje více vektorů přerušení nebo zpráv a pokud chcete synchronizovat zpracování těchto přerušení ovladače, můžete přiřadit jeden zámek otáčení více objektů přerušení DIRQL. Rámec určuje nejvyšší DIRQL sady přerušení a vždy získá spinový zámek na úrovni DIRQL, takže synchronizovaný kód nemůže být přerušen žádnými vektory přerušení ani zprávami v sadě.
Pro objekty přerušení na pasivní úrovni rámec získá zámek přerušení na pasivní úrovni před tím, než zavolá funkci zpětného volání EvtInterruptIsr ovladače při IRQL = PASSIVE_LEVEL. V důsledku toho musí všechny rutiny, které přistupují k vyrovnávací paměti, získat zámek přerušení nebo interně synchronizovat přístup do vyrovnávací paměti. Obvykle je funkce zpětného volání přerušení EvtInterruptWorkItem jedinou další rutinou, která přistupuje k vyrovnávací paměti. Informace o získání zámku přerušení z funkce zpětného volání EvtInterruptWorkItem naleznete v části Poznámky na této stránce.
Také můžete synchronizovat zpracování více vektorů přerušení ovladače tím, že přiřadíte jeden zámek čekání několika objektům přerušení na pasivní úrovni.
Pokud se některé z vašich kódů, které zpracovávají přerušení DIRQL, musí spouštět v IRQL = PASSIVE_LEVEL, může funkce zpětného volání EvtInterruptDpc nebo EvtDpcFunc vytvořit jednu nebo více pracovních položek , aby kód běžel jako funkce zpětného volání EvtWorkItem .
V KMDF verzi 1.11 a novější může ovladač požádat o pracovní položku pro přerušení voláním WdfInterruptQueueWorkItemForIsr. (Vzpomeňte si, že funkce zpětného volání EvtInterruptIsr ovladače může volat WdfInterruptQueueWorkItemForIsr nebo WdfInterruptQueueDpcForIsr, ale ne obojí.)
Pokud je důležité synchronizovat funkce zpětného volání EvtInterruptDpc a EvtDpcFunc navzájem vedle sebe a s ostatními funkcemi zpětného volání, které jsou přidruženy k zařízení, může váš ovladač nastavit člena AutomaticSerialization na hodnotu TRUE ve struktuře WDF_INTERRUPT_CONFIG přerušení a ve struktuře objektu DPC WDF_DPC_CONFIG. Ovladač může také používat zámky zatáčení architektury. (Nastavení členu AutomaticSerialization na PRAVDA nesynchronizuje zpětnou volací funkci EvtInterruptIsr s jinými zpětnými volacími funkcemi. K synchronizaci zpětné volací funkce EvtInterruptIsr použijte WdfInterruptSynchronize nebo WdfInterruptAcquireLock, jak bylo popsáno výše v tomto tématu.)
Další informace o synchronizaci rutin ovladačů naleznete v tématu Techniky synchronizace pro Framework-Based Ovladače.