Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
L'IRQL al quale viene eseguita una routine del driver determina quale routine di supporto del driver in modalità kernel può chiamare. Ad esempio, alcune routine di supporto del driver richiedono che il chiamante operi a IRQL = DISPATCH_LEVEL. Altri non possono essere chiamati in modo sicuro se il chiamante è in esecuzione in qualsiasi IRQL superiore a PASSIVE_LEVEL.
Di seguito è riportato un elenco di IRQLs in cui vengono chiamate le routine del driver standard più comunemente implementate. Gli IRQLs sono elencati tra la priorità più bassa e quella più alta.
PASSIVE_LEVEL
Interruzioni mascherate - Nessuno.
Routine driver chiamate in PASSIVE_LEVEL - DriverEntry, AddDevice, Reinizialize, Scarica routine, maggior parte delle routine dispatch, thread creati dal driver, callback del thread di lavoro.
APC_LEVEL
Interruzioni mascherate - le interruzioni al livello APC_LEVEL vengono mascherate.
Routine dei driver chiamate a APC_LEVEL - Alcune routine di dispatch (vedere Routine di dispatch e IRQL).
DISPATCH_LEVEL
Interruzioni disattivate : DISPATCH_LEVEL e APC_LEVEL interrupt vengono mascherati. Possono verificarsi interruzioni di dispositivo, orologio e interruzioni di alimentazione.
Routine driver chiamate in DISPATCH_LEVEL - StartIo, AdapterControl, AdapterListControl, ControllerControl, IoTimer, Cancel (tenendo premuto il blocco di selezione annulla), DpcForIsr, CustomTimerDpc, routine CustomDpc .
DIRQL
Interruzioni disabilitate - Tutte le interruzioni con IRQL pari al DIRQL dell'oggetto interrupt del driver. Gli interrupt del dispositivo con un valore DIRQL più elevato possono verificarsi, insieme a interruzioni di clock e interruzioni dell'alimentazione.
Routine del driver chiamate in DIRQL - InterruptService, routine SynchCritSection .
L'unica differenza tra APC_LEVEL e PASSIVE_LEVEL è che un processo in esecuzione in APC_LEVEL non può ricevere interrupt APC. Tuttavia, entrambi gli IRQLs implicano un contesto di thread e entrambi implicano che il codice può essere inserito in pagine.
I driver di livello più basso elaborano le IRP mentre operano a uno dei tre IRQL.
PASSIVE_LEVEL, senza interruzioni mascherate sul processore, nelle routine Dispatch del driver
Anche le routine DriverEntry, AddDevice, Reinitialize e Scarica vengono eseguite in PASSIVE_LEVEL, come tutti i thread di sistema creati dal driver.
DISPATCH_LEVEL, con DISPATCH_LEVEL e APC_LEVEL le interruzioni mascherate nel processore, nella routine StartIo
AdapterControl, AdapterListControl, ControllerControl, IoTimer, Cancel (mentre trattiene il blocco spin di annullamento), e le routine CustomTimerDpc vengono eseguite anche in DISPATCH_LEVEL, così come le routine DpcForIsr e CustomDpc.
DEVICE IRQL (DIRQL), con tutti gli interrupt a un livello minore o uguale al SynchronizeIrql degli oggetti di interruzione del driver mascherati sul processore, nelle routine ISR e SynchCritSection
La maggior parte dei driver di livello superiore elabora i pacchetti di richiesta di I/O mentre si esegue a uno dei due IRQL:
PASSIVE_LEVEL, senza interruzioni mascherate sul processore, nelle routine di invio del driver
Anche le routine DriverEntry, Reinizialize, AddDevice e Unload vengono eseguite in PASSIVE_LEVEL, come tutti i thread di sistema creati dal driver o le routine di callback del thread di lavoro o i driver del file system.
DISPATCH_LEVEL, con gli interrupt DISPATCH_LEVEL e APC_LEVEL mascherati sul processore, nelle routine IoCompletion del driver.
Anche le routine IoTimer, Cancel e CustomTimerDpc vengono eseguite in DISPATCH_LEVEL.
In alcune circostanze, i driver intermedi e di livello più basso dei dispositivi di archiviazione di massa vengono chiamati in IRQL APC_LEVEL. In particolare, ciò può verificarsi in corrispondenza di un errore di pagina per il quale un driver del file system invia una richiesta di IRP_MJ_READ a driver inferiori.
La maggior parte delle routine standard dei driver viene eseguita a un IRQL che consente semplicemente di chiamare le routine di supporto appropriate. Ad esempio, un driver di dispositivo deve chiamare AllocateAdapterChannel mentre opera a IRQL DISPATCH_LEVEL. Poiché la maggior parte dei driver di dispositivo chiama queste routine da una routine StartIo , in genere sono già in esecuzione in DISPATCH_LEVEL.
Un driver di dispositivo che non ha una routine StartIo perché configura e gestisce le proprie code di IRP non sta necessariamente funzionando a livello IRQL DISPATCH_LEVEL quando deve chiamare AllocateAdapterChannel. Tale driver deve annidare la chiamata a AllocateAdapterChannel tra le chiamate a KeRaiseIrql e KeLowerIrql in modo che venga eseguito all'IRQL richiesto quando chiama AllocateAdapterChannel e riporti l'IRQL originale quando la routine chiamante riprende il controllo.
Quando si chiamano routine di supporto driver, tenere presente quanto segue.
La chiamata a KeRaiseIrql con un valore NewIrql di input minore dell'IRQL corrente causa un errore irreversibile. La chiamata a KeLowerIrql , ad eccezione del ripristino dell'IRQL originale (ovvero dopo una chiamata a KeRaiseIrql) genera anche un errore irreversibile.
Durante l'esecuzione in IRQL >= DISPATCH_LEVEL, la chiamata di KeWaitForSingleObject o KeWaitForMultipleObjects per gli oggetti dispatcher definiti dal kernel per attendere un intervallo diverso da zero causa un errore irreversibile.
Le uniche routine driver che possono attendere in modo sicuro che eventi, semafori, mutex o timer siano impostati sullo stato segnalato sono quelle eseguite in un contesto di thread non arbitrario a IRQL PASSIVE_LEVEL, come i thread creati dal driver, le routine DriverEntry e Reinitialize, o le routine di invio per operazioni di I/O intrinsecamente sincrone (come la maggior parte delle richieste di controllo I/O del dispositivo).
Anche durante l'esecuzione in IRQL PASSIVE_LEVEL, il codice del driver pageable non deve chiamare KeSetEvent, KeReleaseSemaphore o KeReleaseMutex con il parametro Wait di input impostato su TRUE. Una chiamata di questo tipo può causare un errore di pagina irreversibile.
Qualsiasi routine in esecuzione con un valore maggiore di IRQL APC_LEVEL non può allocare memoria dal pool di paging o accedere alla memoria nel pool di paging in modo sicuro. Se una routine in esecuzione in IRQL maggiore di APC_LEVEL causa un errore di pagina, si tratta di un errore irreversibile.
Un driver deve essere in esecuzione in IRQL DISPATCH_LEVEL quando chiama KeAcquireSpinLockAtDpcLevel e KeReleaseSpinLockFromDpcLevel.
Un driver può essere eseguito in IRQL <= DISPATCH_LEVEL quando chiama KeAcquireSpinLock , ma deve rilasciare tale blocco spin chiamando KeReleaseSpinLock. In altre parole, è un errore di programmazione rilasciare un blocco spin acquisito con KeAcquireSpinLock chiamando KeReleaseSpinLockFromDpcLevel.
Un driver non deve chiamare KeAcquireSpinLockAtDpcLevel, KeReleaseSpinLockFromDpcLevel, KeAcquireSpinLock o KeReleaseSpinLock mentre si opera a IRQL > DISPATCH_LEVEL.
La chiamata a una routine di supporto che utilizza uno spin lock, come una routine ExInterlockedXxx, aumenta l'IRQL sul processore corrente a DISPATCH_LEVEL o DIRQL se il chiamante non è già in esecuzione a un IRQL elevato.
Il codice del driver eseguito in IRQL > PASSIVE_LEVEL deve essere eseguito il più rapidamente possibile. Maggiore è l'IRQL in corrispondenza del quale viene eseguita una routine, più importante è che le prestazioni complessive siano ottimali per ottimizzare tale routine per l'esecuzione il più rapidamente possibile. Ad esempio, qualsiasi driver che chiama KeRaiseIrql deve effettuare la chiamata reciproca a KeLowerIrql non appena può.
Per ulteriori informazioni sulla determinazione delle priorità, vedere il white paper Pianificazione, contesto thread e IRQL.