Richiesta di I/O di esempio - Dettagli
La figura che illustra l'apertura di un oggetto file mostra un'IRP con due posizioni dello stack di I/O, ma un'IRP può avere un numero qualsiasi di posizioni dello stack I/O, a seconda del numero di driver a livelli che gestiranno una determinata richiesta.
La figura seguente illustra in modo più dettagliato il modo in cui i driver nella figura Apertura di un oggetto file usano le routine di supporto di I/O (routine IoXxx ) per elaborare l'IRP per una richiesta di lettura o scrittura.
Il gestore I/O chiama il driver di file system (FSD) con l'IRP allocato per la richiesta di lettura/scrittura del sottosistema. FsD accede alla posizione dello stack I/O nell'IRP per determinare l'operazione che deve eseguire.
FsD può suddividere la richiesta originale in richieste più piccole (possibilmente per più di un driver di dispositivo) chiamando una routine di supporto di I/O (IoAllocateIrp) una o più volte per allocare altri IRP. Gli indirizzi di integrazione aggiuntivi vengono restituiti all'FSD con posizioni dello stack di I/O con riempimento zero per i driver di livello inferiore. A sua discrezione, il FSD può riutilizzare l'IRP originale, anziché allocare altri IRP, come illustrato nella figura precedente, configurando la posizione dello stack I/O del driver inferiore successivo nell'IRP originale e passandolo a driver inferiori.
Per ogni IRP allocato dal driver, l'FSD nella figura precedente chiama una routine di supporto di I/O per registrare una routine di completamento fornita da FSD; nella routine di completamento, il FSD può determinare se i driver inferiori hanno soddisfatto la richiesta e possono liberare ogni IRP allocata dal driver quando sono stati completati i driver inferiori. Il gestore di I/O chiamerà la routine di completamento fornita da FSD se ogni IRP allocata dal driver è stata completata correttamente, completata con uno stato di errore o annullata. Un driver di livello superiore è responsabile del liberamento di tutti gli IRP allocati e viene configurato per conto proprio per i driver di livello inferiore. Il gestore di I/O libera gli indirizzi IP allocati dopo che tutti i driver li hanno completati.
Successivamente, fsD chiama una routine di supporto di I/O (IoGetNextIrpStackLocation) per accedere alla posizione dello stack I/O di livello inferiore successivo per configurare la richiesta per il driver inferiore successivo. Nella figura precedente, il driver inferiore successivo si verifica come il driver di livello più basso. FsD chiama quindi una routine di supporto di I/O (IoCallDriver) per passare tale IRP al driver inferiore successivo.
Quando viene chiamato con l'IRP, il driver di livello più basso controlla la posizione dello stack I/O per determinare l'operazione (indicata dal codice della funzione IRP_MJ_XXX) che deve eseguire sul dispositivo di destinazione. Il dispositivo di destinazione è rappresentato dall'oggetto dispositivo nella posizione dello stack I/O designato e viene passato con l'IRP al driver. Il driver di livello più basso può presumere che il gestore di I/O abbia instradato l'IRP a un punto di ingresso definito per l'operazione IRP_MJ_XXX (qui IRP_MJ_READ o IRP_MJ_WRITE) e che il driver di livello superiore abbia controllato la validità di altri parametri per la richiesta.
Se non esiste alcun driver di livello superiore, il driver di livello più basso verifica se i parametri di input per un'operazione IRP_MJ_XXX sono validi. In caso affermativo, il driver chiama in genere le routine di supporto di I/O per indicare al gestore I/O che un'operazione del dispositivo è in sospeso nell'IRP e per accodare l'IRP o passarla a un'altra routine fornita dal driver che accede al dispositivo di destinazione (qui, un dispositivo fisico o logico: il disco o una partizione sul disco).
Il gestore I/O determina se il driver è già occupato a elaborare un altro IRP per il dispositivo di destinazione, accoda l'IRP se è e restituisce. In caso contrario, il gestore I/O indirizza l'IRP a una routine fornita dal driver che avvia l'operazione di I/O nel dispositivo. In questa fase, entrambi i driver nella figura precedente e il controllo restituito di gestione I/O.
Quando il dispositivo interrompe, la routine del servizio di interruzione del driver (ISR) funziona solo come deve interrompere il dispositivo e salvare il contesto necessario per l'operazione. L'ISR chiama quindi una routine di supporto di I/O (IoRequestDpc) con L'IRP per accodare una routine DPC fornita dal driver (chiamata di procedura posticipata) per completare l'operazione richiesta con una priorità hardware inferiore rispetto all'ISR.
Quando il DPC del driver ottiene il controllo, usa il contesto (passato nella chiamata di ISR a IoRequestDpc) per completare l'operazione di I/O. Il DPC chiama una routine di supporto per dequeuere il successivo IRP (se presente) e passare tale IRP alla routine fornita dal driver che avvia le operazioni di I/O nel dispositivo (vedere Passaggio 5). Il DPC imposta quindi lo stato sull'operazione appena completata nel blocco di stato I/O di I/O di I/O e lo restituisce al gestore di IoCompleteRequest.
Il gestore I/O zero la posizione dello stack I/O del driver di livello più basso nell'IRP e chiama la routine di completamento registrata del file system (vedere Passaggio 3) con l'IRP allocata da FSD. Questa routine di completamento controlla il blocco di stato di I/O per determinare se ripetere la richiesta o aggiornare qualsiasi stato interno mantenuto sulla richiesta originale e liberare l'IRP allocata dal driver. Il file system può raccogliere informazioni sullo stato per tutti gli INDIRIZZI IR allocati dal driver inviati a driver di livello inferiore in modo che possa impostare lo stato di I/O e completare l'IRP originale. Al termine del file system l'IRP originale, la gestione I/O restituisce e il valore NTSTATUS al richiedente originale (funzione nativa del sottosistema) dell'operazione di I/O.
Analogamente al driver del file system illustrato nella figura Elaborazione irp nella figura Driver a livelli, tutti i nuovi driver aggiunti a una catena di driver esistenti possono eseguire tutte le operazioni seguenti:
Impostare la propria routine di completamento in un'istanza di IRP. La routine IoCompletion controlla il blocco di stato di I/O per determinare se i driver inferiori hanno completato correttamente l'IRP, annullato l'IRP e/o completato con un errore. La routine di completamento può anche aggiornare qualsiasi stato specifico di IRP che il driver potrebbe aver salvato, rilasciare tutte le risorse specifiche dell'operazione che il driver potrebbe avere allocato e così via, prima di completare l'IRP. Inoltre, la routine di completamento può rinviare il completamento di IRP (informando il gestore di I/O che è necessaria più elaborazione nell'IRP) e può inviare un'altra richiesta al driver di livello inferiore successivo prima di consentire il completamento dell'IRP.
Configurare la posizione dello stack I/O del driver di livello inferiore successivo negli indirizzi IP allocati e inviare richieste al driver di livello inferiore successivo.
Passare le richieste in ingresso ai driver inferiori configurando la posizione dello stack I/O del driver successivo in ogni IRP e chiamando IoCallDriver. Si noti che per i provider di servizi di integrazione con codice di funzione principale IRP_MJ_POWER, i driver devono usare PoCallDriver.
Ogni oggetto dispositivo creato dal driver rappresenta un dispositivo fisico, logico o virtuale per cui un determinato driver esegue richieste di I/O. Per informazioni dettagliate sulla creazione e la configurazione di un oggetto dispositivo, vedere Oggetti dispositivo e Stack di dispositivi.
Come illustrato anche nella figura Elaborazione irp in driver a livelli, la maggior parte dei driver elabora ogni IRP in fasi tramite un set di routine standard definite dal sistema, ma i driver a livelli diversi in una catena hanno necessariamente routine standard diverse. Ad esempio, solo i driver di livello più basso gestiscono gli interruzioni da un dispositivo fisico, quindi solo un driver di livello più basso avrà un ISR e un DPC che completa le operazioni di I/O basate su interruzioni. D'altra parte, perché tale driver sa che I/O è completato quando riceve un interruzione dal suo dispositivo, non ha bisogno di una routine di completamento. Solo un driver di livello superiore avrà una o più routine di completamento come fsD in questa figura.