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.
Mentre il timer per l'oggetto dispositivo associato è abilitato, la routine IoTimer viene chiamata approssimativamente una volta al secondo. Tuttavia, poiché gli intervalli in cui ogni routine IoTimer viene chiamata dipende dalla risoluzione dell'orologio di sistema, non presupporre che una routine IoTimer venga chiamata esattamente su un limite di un secondo.
Nota Una routine IoTimer , come tutte le routine DPC, viene chiamata in IRQL = DISPATCH_LEVEL. Durante l'esecuzione di una routine DPC, tutti i thread non possono essere eseguiti nello stesso processore. Gli sviluppatori di driver devono progettare attentamente le routine IoTimer per l'esecuzione per un breve periodo di tempo possibile.
Forse l'uso più comune per una routine IoTimer consiste nel timeout delle operazioni di I/O del dispositivo per un IRP. Si consideri lo scenario seguente per l'uso di una routine IoTimer come timer in esecuzione all'interno di un driver di dispositivo:
All'avvio del dispositivo, il driver inizializza un contatore timer nell'estensione del dispositivo su -1, che indica che non sono presenti operazioni di I/O del dispositivo correnti e chiama IoStartTimer subito prima che restituisca STATUS_SUCCESS.
Ogni volta che viene chiamata la routine IoTimer , controlla se il contatore timer è -1 e, in tal caso, restituisce il controllo.
La routine StartIo del driver inizializza il contatore timer nell'estensione del dispositivo a un limite superiore, più un secondo aggiuntivo nel caso in cui la routine IoTimer sia stata appena eseguita. Usa quindi KeSynchronizeExecution per chiamare una routine SynchCritSection_1 , che programma il dispositivo fisico per l'operazione richiesta dall'IRP corrente.
L'ISR del driver reimposta il contatore timer su -1 prima di accodare la routine DpcForIsr del driver o una routine CustomDpc .
Ogni volta che viene chiamata la routine IoTimer , controlla se il contatore timer è stato reimpostato dall'ISR su -1 e, in tal caso, restituisce il controllo . In caso contrario, la routine IoTimer usa KeSynchronizeExecution per chiamare una routine SynchCritSection_2 , che regola il contatore timer in base a un numero determinato di secondi dal driver.
La routine SynchCritSection_2 restituisce TRUE alla routine IoTimer purché la richiesta corrente non sia ancora scaduta. Se il contatore timer passa a zero, la routine SynchCritSection_2 reimposta il contatore del timer su un valore di reset-timeout determinato dal driver, imposta un flag previsto per se stesso (e per DpcForIsr) nell'area di contesto, tenta di reimpostare il dispositivo e restituisce TRUE.
La routine SynchCritSection_2 verrà chiamata di nuovo se si verifica anche il timeout dell'operazione di reimpostazione nel dispositivo, quando restituisce FALSE. Se la reimpostazione ha esito positivo, la routine DpcForIsr determina che il dispositivo è stato reimpostato dal flag previsto per il ripristino e ritenta la richiesta, ripetendo le azioni della routine StartIo come descritto nel passaggio 2.
Se la routine SynchCritSection_2 restituisce FALSE, la routine IoTimer presuppone che il dispositivo fisico sia in uno stato sconosciuto perché un tentativo di reimpostazione non è già riuscito. In queste circostanze, la routine IoTimer accoda una routine CustomDpc e restituisce. Questa routine CustomDpc registra un errore di I/O del dispositivo, chiama IoStartNextPacket, non riesce l'IRP corrente e restituisce.
Se l'ISR del driver del dispositivo reimposta il contatore del timer condiviso a -1, come descritto nel passaggio 3, la routine DpcForIsr del driver completa l'elaborazione di I/O guidata da interrupt dell'IRP corrente. Il contatore timer di reimpostazione indica che l'operazione di I/O del dispositivo non è scaduta, quindi la routine IoTimer non deve modificare il contatore timer.
Nella maggior parte dei casi, la routine SynchCritSection_2 precedente decrementa semplicemente il contatore timer. La routine SynchCritSection_2 tenta di reimpostare il dispositivo solo se si è verificato il timeout dell'operazione di I/O corrente, che viene indicato quando il contatore timer passa a zero. E solo se un tentativo di reimpostare il dispositivo non è già riuscito, la routine SynchCritSection_2 restituisce FALSE alla routine IoTimer .
Di conseguenza, sia la routine IoTimer precedente che il relativo helper SynchCritSection_2 routine richiedono molto poco tempo per l'esecuzione in circostanze normali. Usando una routine IoTimer in questo modo, un driver di dispositivo garantisce che ogni richiesta di I/O del dispositivo valida possa essere ritentata, se necessario e che una routine CustomDpc non riuscirà un IRP solo se un errore hardware non verificabile impedisce che l'IRP venga soddisfatto. Inoltre, il driver fornisce questa funzionalità a un costo molto minimo nel tempo di esecuzione.
La semplicità dello scenario precedente dipende da un dispositivo che esegue una sola operazione alla volta e da un driver che normalmente non si sovrappone alle operazioni di I/O. Un driver che esegue operazioni di I/O sovrapposte del dispositivo o un driver di livello superiore che utilizza una routine IoTimer per temporizzare un set di IRP allocati dal driver inviati a più catene di driver inferiori, avrebbe scenari di timeout più complessi da gestire.