Condividi tramite


Uso dell'I/O memorizzato nel buffer

Un driver che esegue il servizio di un dispositivo interattivo o lento o che in genere trasferisce quantità relativamente piccole di dati alla volta, deve usare il metodo di trasferimento di I/O memorizzato nel buffer . L'uso di operazioni di I/O memorizzate nel buffer per trasferimenti interattivi di piccole dimensioni migliora l'utilizzo complessivo della memoria fisica, perché il gestore della memoria non deve bloccare una pagina fisica completa per ogni trasferimento, così come per i driver che richiedono operazioni di I/O dirette. In genere, video, tastiera, mouse, seriale e driver paralleli richiedono I/O memorizzati nel buffer.

Il gestore di I/O determina che un'operazione di I/O usa operazioni di I/O memorizzate nel buffer come indicato di seguito:

La figura seguente illustra come il gestore di I/O configura una richiesta di IRP_MJ_READ per un'operazione di trasferimento che usa operazioni di I/O memorizzate nel buffer.

diagramma che illustra un i/o memorizzato nel buffer degli utenti.

La figura mostra una panoramica del modo in cui i driver possono usare il puntatore SystemBuffer nell'IRP per trasferire dei dati per la richiesta di lettura, quando un driver ha eseguito l'operazione OR con i flag dell'oggetto dispositivo con DO_BUFFERED_IO.

  1. Alcuni intervalli di indirizzi virtuali dello spazio utente rappresentano il buffer del thread corrente e il contenuto del buffer potrebbe essere archiviato in un intervallo di indirizzi fisici basati su pagina (ombreggiatura scura nella figura precedente).

  2. Il gestore di I/O esegue la richiesta di lettura del thread corrente, per cui il thread passa un intervallo di indirizzi virtuali dello spazio utente che rappresentano un buffer.

  3. Il gestore I/O controlla l'accessibilità del buffer fornito dall'utente e chiama ExAllocatePoolWithTag per creare un buffer di spazio di sistema non di paging (SystemBuffer) delle dimensioni del buffer fornito dall'utente.

  4. Il gestore di I/O fornisce l'accesso al SystemBuffer appena allocato nell'IRP inviato al driver.

    Se la figura mostra una richiesta di scrittura, il gestore di I/O copia i dati dal buffer utente nel buffer di sistema prima dell'invio dell'IRP al driver.

  5. Per la richiesta di lettura illustrata nella figura precedente, il driver legge i dati dal dispositivo nel buffer dello spazio di sistema. La memoria per questo buffer non è di pagina e il driver può accedere in modo sicuro al buffer senza prima bloccarlo. Quando la richiesta di lettura è stata soddisfatta, il driver chiama IoCompleteRequest con IRP.

  6. Quando il thread originale è di nuovo attivo, il gestore di I/O copia i dati di lettura dal buffer di sistema nel buffer utente. Chiama anche ExFreePool per rilasciare il buffer di sistema.

Dopo che il gestore di I/O ha creato un buffer dello spazio di sistema per il driver, il thread in modalità utente richiedente può essere scambiato e la sua memoria fisica può essere riutilizzata da un altro thread, possibilmente da un thread appartenente a un altro processo. Tuttavia, l'intervallo di indirizzi virtuali dello spazio di sistema fornito in IRP rimane valido fino a quando il driver chiama IoCompleteRequest con IRP.

I driver che trasferiscono grandi quantità di dati alla volta, in particolare i driver che eseguono trasferimenti a più pagine, non devono tentare di usare operazioni di I/O memorizzate nel buffer. Durante l'esecuzione del sistema, il pool non paginato può diventare frammentato, impedendo al gestore di I/O di allocare grandi buffer di spazio di sistema contigui da inviare negli IRP per quel driver.

In genere, un driver utilizza l'I/O buffered per alcuni tipi di IRP, come le richieste di IRP_MJ_DEVICE_CONTROL, anche se utilizza anche l'I/O diretto. I driver che usano operazioni di I/O dirette vengono in genere utilizzati solo per le richieste di IRP_MJ_READ e IRP_MJ_WRITE, e possibilmente IRP_MJ_INTERNAL_DEVICE_CONTROL definite dal driver che richiedono trasferimenti di dati di grandi dimensioni.

Ogni IRP_MJ_DEVICE_CONTROL e IRP_MJ_INTERNAL_DEVICE_CONTROL richiesta include un codice di controllo I/O. Se il codice di controllo di I/O indica che l'IRP deve essere supportato tramite I/O memorizzato nel buffer, il gestore di I/O usa un singolo buffer di sistema per rappresentare i buffer di input e output dell'applicazione utente. Un driver che supporta tale codice di controllo di I/O deve leggere i dati di input (se presenti) dal buffer e quindi fornire i dati di output (se presenti) sovrascrivendo i dati di input. Per altre informazioni, vedere Definizione dei codici di controllo di I/O.