Condividi tramite


Accesso ai buffer di dati nei driver UMDF 1.x

Avviso

UMDF 2 è la versione più recente di UMDF e sostituisce UMDF 1. Tutti i nuovi driver UMDF devono essere scritti usando UMDF 2. Non vengono aggiunte nuove funzionalità a UMDF 1 ed è disponibile un supporto limitato per UMDF 1 nelle versioni più recenti di Windows 10. I driver di Windows universali devono usare UMDF 2.

Per altre info, vedi Introduzione con UMDF.

Per informazioni sull'accesso ai buffer di dati per UMDF 2, vedere Accesso ai buffer dei dati nei driver WDF.

Quando un driver riceve una richiesta di controllo di I/O di lettura, scrittura o dispositivo, l'oggetto richiesta contiene un buffer di input o un buffer di output o entrambi. Alcune richieste di controllo di I/O del dispositivo forniscono due input, due output o due buffer di input/output.

I buffer di input contengono informazioni necessarie al driver. Per le richieste di scrittura, in genere queste informazioni sono dati che un driver di funzione deve inviare a un dispositivo. Per le richieste di controllo di I/O del dispositivo, un buffer di input potrebbe contenere informazioni che indicano il tipo di operazione che il driver deve eseguire.

I buffer di output ricevono informazioni dal driver. Per le richieste di lettura, in genere queste informazioni sono dati ricevuti da un driver di funzione da un dispositivo. Per le richieste di controllo di I/O del dispositivo, un buffer di output potrebbe ricevere lo stato o altre informazioni sul codice di controllo di I/O della richiesta specificata.

La tecnica usata dal driver per accedere ai buffer di dati di una richiesta può dipendere dal metodo del driver per accedere ai buffer di dati per un dispositivo. UMDF supporta i metodi di accesso al buffer seguenti:

Un terzo metodo di accesso, chiamato non memorizzato nel buffer né in I/O diretto, non è disponibile per i driver basati su UMDF, ma UMDF può convertire alcune richieste di I/O dal metodo "nessuno" a un metodo supportato dalla versione UMDF.

Nella maggior parte dei casi, i driver basati su UMDF chiamano gli stessi metodi di oggetto UMDF per accedere ai buffer di dati, indipendentemente dal fatto che UMDF e il driver usino operazioni di I/O memorizzate nel buffer o I/O dirette. L'I/O diretto offre spesso prestazioni migliori rispetto alle prestazioni di I/O del buffer.

Le sezioni seguenti di questo argomento illustrano:

Specifica di un metodo di accesso al buffer preferito

Le versioni UMDF 1.9 e successive supportano sia i metodi di accesso I/O memorizzati nel buffer che diretti. I driver possono specificare il metodo di accesso che si preferisce usare per tutte le richieste di controllo di I/O di lettura, scrittura e dispositivo di un dispositivo chiamando IWDFDeviceInitialize2::SetIoTypePreference prima di chiamare IWDFDriver::CreateDevice per creare un oggetto dispositivo. Ad esempio, se un driver specifica una preferenza solo per il metodo di I/O memorizzato nel buffer per le richieste di lettura e scrittura per uno dei dispositivi, il processo host del driver UMDF usa il metodo di I/O memorizzato nel buffer quando recapita richieste di lettura e scrittura al driver per tale dispositivo. Se un driver specifica una preferenza per l'I/O diretto, UMDF può (ma non) usare I/O diretto. Per altre informazioni su quando UMDF usa operazioni di I/O dirette, vedere How UMDF Chooses a Buffer Access Method for an I/O Request .For more information about when UMDF uses direct I/O, see How UMDF Chooses a Buffer Access Method for an I/O Request.

Per ogni dispositivo supportato da un driver, il driver può specificare una preferenza per l'I/O memorizzato nel buffer, per le operazioni di I/O dirette o memorizzate nel buffer per il dispositivo. Il driver può specificare un tipo di metodo di accesso per le richieste di lettura e scrittura e un altro tipo di metodo di accesso per le richieste di controllo di I/O del dispositivo. Se il driver non specifica una preferenza per il metodo di accesso, UMDF usa il metodo memorizzato nel buffer.

Per le richieste di controllo di I/O del dispositivo, il codice di controllo I/O (IOCTL) specifica il metodo di accesso al buffer. Per altre informazioni su come gli IOCTL specificano un metodo di accesso, vedere Definizione dei codici di controllo I/O. Tuttavia, il metodo di accesso usato da UMDF potrebbe non corrispondere al metodo di accesso specificato da IOCTL.

  • Nelle versioni di UMDF precedenti alla versione 1.9, UMDF usa sempre il metodo di accesso memorizzato nel buffer per tutte le richieste di controllo di I/O.

  • Le versioni UMDF 1.9 e successive usano il metodo di accesso I/O memorizzato nel buffer se IOCTL specifica le operazioni di I/O memorizzate nel buffer. Se IOCTL specifica l'I/O diretto e se il driver chiama IWDFDeviceInitialize2::SetIoTypePreference per indicare che una preferenza per l'I/O diretto, UMDF potrebbe usare I/O diretto oppure potrebbe usare I/O memorizzati nel buffer, come descritto in Come UMDF sceglie un metodo di accesso al buffer per una richiesta di I/O. Per informazioni sul modo in cui UMDF supporta IOCTL che specificano il metodo "I/O memorizzato nel buffer né I/O diretto", vedere Using Neither Buffered I/O nor Direct I/O in UMDF Drivers.For information about how UMDF supports IOCTLs that specify the "nor buffered I/O method" method, see Using Neither Buffered I/O nor Direct I/O in UMDF Drivers.

Specifica di una modalità di recupero buffer

Nelle versioni di UMDF precedenti alla versione 1.9, UMDF rende sempre disponibili i buffer di una richiesta di I/O al driver (copiando i buffer nel processo host del driver UMDF) non appena UMDF riceve la richiesta di I/O. Questa modalità di recupero del buffer è denominata recupero immediato. Se si verifica un errore, UMDF completa la richiesta di I/O con un valore di stato di errore e non recapita la richiesta di I/O al driver.

Le versioni UMDF 1.9 e successive supportano sia modalità di recupero immediato che di recupero posticipato . La modalità di recupero posticipata posticipa la copia del buffer di una richiesta di I/O nel processo host del driver fino a quando il driver tenta di accedere al buffer. Se si verifica un errore, le funzioni di accesso al buffer restituiscono un valore di stato di errore al driver.

Il driver può specificare una modalità di recupero del buffer quando chiama IWDFDeviceInitialize2::SetIoTypePreference per ogni dispositivo. Usare le regole seguenti:

  • Se il driver specifica il metodo di accesso diretto di I/O, deve specificare anche la modalità di recupero posticipata. L'I/O diretto funziona solo con il recupero posticipato.

  • Tutti i driver scritti per l'esecuzione con UMDF versioni 1.9 e successive devono specificare la modalità di recupero posticipata per tutte le richieste di I/O, indipendentemente dal fatto che il driver scelga il metodo di accesso di I/O memorizzato nel buffer o diretto. Il recupero posticipato offre prestazioni migliori perché non accede ai buffer che il driver non usa.

Se il driver non specifica una modalità di recupero del buffer, UMDF usa il recupero immediato.

Tutti i driver basati su UMDF in uno stack di driver devono usare la stessa modalità di recupero. Se alcuni driver specificano il recupero immediato e alcuni specificano il recupero posticipato, UMDF usa il recupero immediato.

Come UMDF sceglie un metodo di accesso al buffer per una richiesta di I/O

Il metodo di accesso specificato da un driver quando chiama IWDFDeviceInitialize2::SetIoTypePreference potrebbe non essere quello usato da UMDF. UMDF usa le regole seguenti per determinare quale metodo di accesso usare:

  • Tutti i driver basati su UMDF in uno stack di driver devono usare lo stesso metodo per accedere ai buffer di un dispositivo. Se UMDF determina che alcuni driver preferiscono l'I/O memorizzato nel buffer o l'I/O diretto per un dispositivo, mentre altri driver preferiscono solo l'I/O memorizzato nel buffer per il dispositivo, UMDF usa L/O memorizzato nel buffer per tutti i driver. Se uno o più driver di uno stack preferiscono solo l'I/O memorizzato nel buffer mentre altri preferiscono solo L/O diretto, UMDF registra un evento nel registro eventi di sistema e non avvia lo stack di driver.

    Il driver può chiamare IWDFDevice2::GetDeviceStackIoTypePreference per determinare i metodi di accesso al buffer assegnati da UMDF alle richieste di lettura/scrittura di un dispositivo e alle richieste di controllo di I/O.

  • In alcuni casi, un driver specifica una preferenza per l'I/O diretto quando chiama IWDFDeviceInitialize2::SetIoTypePreference, ma per ottenere prestazioni ottimali, UMDF usa L/O memorizzato nel buffer per una o più richieste del dispositivo. Ad esempio, UMDF usa L/O memorizzato nel buffer memorizzato nel buffer per piccoli buffer se può copiare i dati nel buffer del driver più velocemente di quanto possa eseguire il mapping dei buffer per l'accesso diretto.

    Facoltativamente, è possibile impostare un valore del Registro di sistema DirectTransferThreshold di tipo REG_DWORD usato dal framework per determinare le dimensioni del buffer più piccole per cui il framework userà le operazioni di I/O dirette. In genere, non è necessario fornire questo valore del Registro di sistema perché il framework usa un valore che fornisce le migliori prestazioni. Il valore DirectTransferThreshold si trova nella sottochiave Device Parameters\WUDF del dispositivo, che si trova sotto la chiave hardware del dispositivo.

    Il framework usa le regole seguenti per determinare la soglia in base al valore specificato in DirectTransferThreshold. I numeri forniti presuppongono un PAGE_SIZE di 4096, che è valido ad eccezione dei sistemi basati su Itanium.

    • Se si imposta DirectTransferThreshold su qualsiasi valore minore o uguale a 8192 (o 2 * PAGE_SIZE), il framework imposta la soglia su 8192. Il framework usa l'I/O memorizzato nel buffer per i buffer inferiori a 8192 byte e l'I/O diretto per i buffer uguali o superiori a 8192 byte.

    • Se si imposta DirectTransferThreshold su qualsiasi valore maggiore di 8192, il framework arrotonda fino al successivo multiplo esatto di PAGE_SIZE. Anche in questo caso, il framework usa l'I/O memorizzato nel buffer per i buffer inferiori alla soglia e l'I/O diretto per i buffer uguali o superiori alla soglia.

  • UMDF usa l'I/O diretto solo per lo spazio del buffer che inizia e termina su un limite di pagina di memoria. Se l'inizio o la fine di un buffer non si trova su un limite di pagina, UMDF usa L/O memorizzato nel buffer per tale parte del buffer. In altre parole, UMDF potrebbe usare le operazioni di I/O memorizzate nel buffer e le operazioni di I/O dirette per un trasferimento di dati di grandi dimensioni costituito da diverse richieste di I/O.

  • Per le richieste di controllo di I/O del dispositivo, UMDF usa operazioni di I/O dirette solo se il codice di controllo I/O (IOCTL) specifica l'I/O diretto e solo se tutti i driver basati su UMDF del dispositivo hanno chiamato IWDFDeviceInitialize2::SetIoTypePreference per specificare il metodo di accesso diretto.

I driver usano lo stesso set di metodi di oggetto richiesta per accedere ai buffer dei dati, indipendentemente dal metodo di accesso al buffer. Di conseguenza, la maggior parte dei driver in genere non deve sapere se UMDF usa operazioni di I/O memorizzate nel buffer o I/O dirette per una richiesta di I/O.

Come un driver può ottenere il metodo di accesso per una richiesta di I/O

In alcuni casi, è possibile migliorare le prestazioni del dispositivo e del driver se il metodo di accesso è noto. In questi casi, il driver può chiamare IWDFIoRequest2::GetEffectiveIoType per ottenere il metodo di accesso al buffer di una richiesta di I/O.

Si consideri ad esempio un dispositivo ad alta velocità effettiva che usa in genere operazioni di I/O dirette. Poiché usa operazioni di I/O dirette, il driver deve copiare i parametri specificati dall'applicazione nella memoria del driver locale prima di convalidare i parametri, per assicurarsi che l'applicazione non modifichi i parametri dopo la convalida.

Poiché il driver può ricevere occasionalmente un buffer che usa operazioni di I/O memorizzate nel buffer e poiché i buffer di I/O memorizzati nel buffer sono già stati copiati, l'applicazione non può modificare i dati e il driver non deve copiare i parametri prima di convalidarli. Pertanto, il driver deve controllare il metodo di accesso al buffer di ogni richiesta per determinare se deve copiare i parametri prima di convalidarli.

Uso dell'I/O memorizzato nel buffer nei driver UMDF

Se il driver usa I/O memorizzato nel buffer, il comportamento di UMDF varia a seconda del tipo di richiesta. Per le richieste di lettura e scrittura, il processo host driver crea un singolo buffer intermedio a cui il driver può accedere.

Per le richieste di scrittura, il processo host del driver trasferisce le informazioni di input dal buffer di input dell'applicazione chiamante prima di chiamare lo stack di driver. I driver in genere leggono le informazioni di input dal buffer intermedio e le scrivono nel dispositivo.

Per le richieste di lettura, i driver in genere leggono informazioni da un dispositivo e le archiviano nel buffer intermedio. Il processo host driver copia i dati di output dal buffer intermedio al buffer di output dell'applicazione.

Per le richieste di controllo di I/O del dispositivo, tuttavia, il processo host driver crea due buffer separati a cui il driver può accedere. Si noti che questo comportamento è diverso dal comportamento dei driver WDM e KMDF, per i quali le richieste di controllo di I/O di lettura, scrittura e dispositivo inviate tramite operazioni di I/O memorizzate nel buffer, comportano l'accesso al driver a un singolo buffer intermedio. In questo caso, il buffer di output inizialmente non contiene nulla e il driver non deve leggerlo. Inoltre, tutti i dati scritti dal driver nel buffer di input vengono eliminati e non restituiti all'applicazione chiamante.

Per linee guida su quando scegliere l'I/O memorizzato nel buffer, vedere WDF_DEVICE_IO_TYPE.

Le versioni UMDF 1.9 e successive possono supportare il recupero immediato o posticipato dei buffer delle richieste. Per altre informazioni, vedere WDF_DEVICE_IO_BUFFER_RETRIEVAL.

Un driver che usa la modalità di recupero immediato del buffer deve usare IWDFIoRequest::GetInputMemory e IWDFIoRequest::GetOutputMemory per accedere ai buffer.

Un driver che usa la modalità di recupero del buffer posticipato può accedere ai buffer chiamando IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer o IWDFIoRequest2::RetrieveOutputMemory.

Uso di I/O diretto nei driver UMDF

Se il driver usa I/O diretto, il processo host del driver verifica l'accessibilità dello spazio buffer specificato dall'origine della richiesta di I/O (in genere un'applicazione in modalità utente), blocca lo spazio del buffer nella memoria fisica e quindi fornisce al driver l'accesso diretto allo spazio del buffer.

Per linee guida su quando scegliere l'I/O diretto, vedere WDF_DEVICE_IO_TYPE.

Il driver può accedere ai buffer chiamando IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer o IWDFIoRequest2::RetrieveOutputMemory.

Uso né di I/O memorizzati nel buffer né di I/O diretto nei driver UMDF

Il metodo di accesso al buffer noto come metodo di I/O non memorizzato nel buffer né diretto (o, per breve, il metodo "nessuno" consente ai driver di accedere direttamente ai puntatori del buffer delle richieste di un'applicazione. I driver basati su UMDF non possono usare questo metodo di accesso.

Tuttavia, le definizioni di alcuni codici di controllo I/O del dispositivo (IOCTL) specificano che le richieste usano il metodo "nessuno". Facoltativamente, UMDF può convertire il metodo di accesso al buffer di tali richieste di controllo di I/O del dispositivo in operazioni di I/O memorizzate nel buffer o I/O diretto. Eseguire la procedura descritta di seguito:

  1. Includere la direttiva UmdfMethodNeitherAction in una sezione INF DDInstall del file INF del driver. È possibile impostare il valore della direttiva per indicare che UMDF deve passare le richieste di controllo di I/O del dispositivo che usano il metodo di accesso "nessuno" al driver. In caso contrario, UMDF completa queste richieste di I/O con un valore di stato di errore.

  2. Accedere ai buffer della richiesta di I/O usando i metodi oggetto forniti da UMDF per le operazioni di I/O memorizzate nel buffer o I/O diretto.

È consigliabile abilitare il supporto delle richieste IOCTL che usano il metodo "nessuno" solo se si è certi che UMDF possa convertire il metodo di accesso in operazioni di I/O memorizzate nel buffer o I/O diretto. Ad esempio, se IOCTL specifica una richiesta personalizzata che non segue le regole di specifica del buffer descritte in Descrizioni buffer per i codici di controllo I/O, UMDF non può convertire i buffer.