Zugreifen auf Datenpuffer in UMDF 1.x-Treibern

Warnung

UMDF 2 ist die neueste Version von UMDF und ersetzt UMDF 1. Alle neuen UMDF-Treiber sollten mit UMDF 2 geschrieben werden. UMDF 1 werden keine neuen Features hinzugefügt, und die Unterstützung für UMDF 1 für neuere Versionen von Windows 10 ist eingeschränkt. Universelle Windows-Treiber müssen UMDF 2 verwenden.

Weitere Informationen finden Sie unter Erste Schritte mit UMDF.

Informationen zum Zugreifen auf Datenpuffer für UMDF 2 finden Sie unter Zugreifen auf Datenpuffer in WDF-Treibern.

Wenn ein Treiber eine Lese-, Schreib- oder Geräte-E/A-Steuerelementanforderung empfängt, enthält das Anforderungsobjekt entweder einen Eingabepuffer oder einen Ausgabepuffer oder beides. (Einige Geräte-E/A-Steuerelementanforderungen bieten zwei Eingabe-, zwei Ausgabe- oder zwei Eingabe-/Ausgabepuffer.)

Eingabepuffer enthalten Informationen, die der Treiber benötigt. Bei Schreibanforderungen sind diese Informationen in der Regel Daten, die ein Funktionstreiber an ein Gerät senden muss. Bei Geräte-E/A-Steuerelementanforderungen kann ein Eingabepuffer Informationen enthalten, die den Typ des Vorgangs angeben, den der Treiber ausführen muss.

Ausgabepuffer empfangen Informationen vom Treiber. Bei Leseanforderungen sind diese Informationen in der Regel Daten, die ein Funktionstreiber von einem Gerät empfängt. Bei Geräte-E/A-Steuerelementanforderungen kann ein Ausgabepuffer status oder andere Informationen empfangen, die der E/A-Steuerungscode der angegebenen Anforderung enthält.

Die Technik, die Ihr Treiber für den Zugriff auf die Datenpuffer einer Anforderung verwendet, kann von der Methode des Treibers für den Zugriff auf Datenpuffer für ein Gerät abhängen. UMDF unterstützt die folgenden Pufferzugriffsmethoden:

Eine dritte Zugriffsmethode, die weder gepuffert noch direkte E/A genannt wird, ist für UMDF-basierte Treiber nicht verfügbar, aber UMDF kann einige E/A-Anforderungen von der "weder"-Methode in eine Methode konvertieren, die von der UMDF-Version unterstützt wird.

In den meisten Fällen rufen UMDF-basierte Treiber dieselben UMDF-Objektmethoden auf, um auf Datenpuffer zuzugreifen, unabhängig davon, ob UMDF und der Treiber gepufferte E/A oder direkte E/A verwenden. Direkte E/A bieten häufig eine bessere Leistung als Puffer-E/A.

In den folgenden Abschnitten dieses Themas wird erläutert:

Angeben einer bevorzugten Pufferzugriffsmethode

UMDF-Versionen 1.9 und höher unterstützen sowohl die gepufferten als auch die direkten E/A-Zugriffsmethoden. Treiber können die Zugriffsmethode angeben, die Sie für alle Lese-, Schreib- und Geräte-E/A-Steuerelementanforderungen eines Geräts verwenden möchten, indem Sie IWDFDeviceInitialize2::SetIoTypePreference aufrufen, bevor Sie IWDFDriver::CreateDevice aufrufen, um ein Geräteobjekt zu erstellen. Wenn ein Treiber beispielsweise eine Einstellung nur für die gepufferte E/A-Methode für Lese- und Schreibanforderungen für eines seiner Geräte angibt, verwendet der UMDF-Treiberhostprozess die gepufferte E/A-Methode, wenn er Lese- und Schreibanforderungen an den Treiber für dieses Gerät übermittelt. Wenn ein Treiber eine Einstellung für direkte E/A angibt, kann UMDF direkte E/A verwenden (kann aber nicht). Weitere Informationen dazu, wann UMDF direkte E/A verwendet, finden Sie unter So wählt UMDF eine Pufferzugriffsmethode für eine E/A-Anforderung aus.

Für jedes Gerät, das ein Treiber unterstützt, kann der Treiber eine Einstellung für gepufferte E/A, direkte E/A oder für gepufferte oder direkte E/A für das Gerät angeben. Der Treiber kann einen Typ von Zugriffsmethode für Lese- und Schreibanforderungen und einen anderen Typ von Zugriffsmethode für Geräte-E/A-Steuerungsanforderungen angeben. Wenn der Treiber keine Zugriffsmethode-Einstellung angibt, verwendet UMDF die gepufferte Methode.

Für Geräte-E/A-Steuerungsanforderungen gibt der E/A-Steuerungscode (IOCTL) die Pufferzugriffsmethode an. (Weitere Informationen dazu, wie IOCTLs eine Zugriffsmethode angeben, finden Sie unter Definieren von E/A-Steuerungscodes.) Die von UMDF verwendete Zugriffsmethode stimmt jedoch möglicherweise nicht mit der Zugriffsmethode überein, die vom IOCTL angegeben wird.

Angeben eines Pufferabrufmodus

In UMDF-Versionen vor Version 1.9 stellt UMDF immer die Puffer einer E/A-Anforderung für den Treiber zur Verfügung (durch Kopieren der Puffer in den UMDF-Treiberhostprozess), sobald UMDF die E/A-Anforderung empfängt. Dieser Pufferabrufmodus wird als sofortiger Abruf bezeichnet. Wenn ein Fehler auftritt, schließt UMDF die E/A-Anforderung mit einem Fehler status Wert ab und übermittelt die E/A-Anforderung nicht an den Treiber.

UMDF-Versionen 1.9 und höher unterstützen sowohl den sofortigen Abruf als auch den verzögerten Abrufmodus . Der verzögerte Abrufmodus verschiebt das Kopieren des Puffers einer E/A-Anforderung in den Treiberhostprozess, bis der Treiber versucht, auf den Puffer zuzugreifen. Wenn ein Fehler auftritt, geben die Pufferzugriffsfunktionen einen Fehler status Wert an den Treiber zurück.

Ihr Treiber kann einen Pufferabrufmodus angeben, wenn er IWDFDeviceInitialize2::SetIoTypePreference für jedes Gerät aufruft. Verwenden Sie die folgenden Regeln:

  • Wenn Ihr Treiber die direkte E/A-Zugriffsmethode angibt, muss er auch den Verzögerten Abrufmodus angeben. Direkte E/A funktioniert nur mit verzögertem Abruf.

  • Alle Treiber, die für die Ausführung mit UMDF-Versionen 1.9 und höher geschrieben wurden, sollten den verzögerten Abrufmodus für alle E/A-Anforderungen angeben, unabhängig davon, ob der Treiber die gepufferte oder direkte E/A-Zugriffsmethode wählt. Der verzögerte Abruf bietet eine bessere Leistung, da er nicht auf Puffer zugreift, die der Treiber nicht verwendet.

Wenn Ihr Treiber keinen Pufferabrufmodus angibt, verwendet UMDF den sofortigen Abruf.

Alle UMDF-basierten Treiber in einem Treiberstapel müssen denselben Abrufmodus verwenden. Wenn einige Treiber den sofortigen Abruf und andere den verzögerten Abruf angeben, verwendet UMDF den sofortigen Abruf.

So wählt UMDF eine Pufferzugriffsmethode für eine E/A-Anforderung aus

Die Zugriffsmethode, die ein Treiber angibt, wenn er IWDFDeviceInitialize2::SetIoTypePreference aufruft, ist möglicherweise nicht die Methode, die UMDF verwendet. UMDF verwendet die folgenden Regeln, um zu bestimmen, welche Zugriffsmethode verwendet werden soll:

  • Alle UMDF-basierten Treiber in einem Treiberstapel müssen dieselbe Methode für den Zugriff auf die Puffer eines Geräts verwenden. Wenn UMDF feststellt, dass einige Treiber entweder gepufferte E/A oder direkte E/A für ein Gerät bevorzugen, während andere Treiber nur gepufferte E/A für das Gerät bevorzugen, verwendet UMDF gepufferte E/A für alle Treiber. Wenn einer oder mehrere Treiber eines Stapels nur gepufferte E/A-Vorgänge bevorzugen, während andere nur direkte E/A bevorzugen, protokolliert UMDF ein Ereignis im Systemereignisprotokoll und startet den Treiberstapel nicht.

    Ihr Treiber kann IWDFDevice2::GetDeviceStackIoTypePreference aufrufen, um die Pufferzugriffsmethoden zu ermitteln, die UMDF den Lese-/Schreibanforderungen und E/A-Steuerelementanforderungen eines Geräts zugewiesen hat.

  • In einigen Fällen gibt ein Treiber eine Präferenz für direkte E/A an, wenn er IWDFDeviceInitialize2::SetIoTypePreference aufruft, aber um eine optimale Leistung zu erzielen, verwendet UMDF gepufferte E/A für eine oder mehrere Anforderungen des Geräts. Beispielsweise verwendet UMDF gepufferte E/A für kleine Puffer, wenn die Daten schneller in den Puffer des Treibers kopiert werden können, als die Puffer für den direkten Zugriff zuordnen kann.

    Optional können Sie einen REG_DWORD typisierten DirectTransferThreshold-Registrierungswert festlegen, den das Framework verwendet, um die kleinste Puffergröße zu bestimmen, für die das Framework direkte E/A verwendet. In der Regel müssen Sie diesen Registrierungswert nicht angeben, da das Framework einen Wert verwendet, der die beste Leistung bietet. Der DirectTransferThreshold-Wert befindet sich unter dem Unterschlüssel Device Parameters\WUDF des Geräts, der sich unter dem Hardwareschlüssel des Geräts befindet.

    Das Framework verwendet die folgenden Regeln, um den Schwellenwert basierend auf dem Wert zu bestimmen, den Sie in DirectTransferThreshold angeben. Die angegebenen Zahlen gehen von einer PAGE_SIZE von 4096 aus, die mit Ausnahme von Itanium-basierten Systemen gültig ist.

    • Wenn Sie DirectTransferThreshold auf einen Wert unter oder gleich 8192 (oder 2 * PAGE_SIZE) festlegen, legt das Framework den Schwellenwert auf 8192 fest. Das Framework verwendet gepufferte E/A-Vorgänge für Puffer, die kleiner als 8192 Bytes sind, und direkte E/A für Puffer mit oder größer als 8192 Bytes.

    • Wenn Sie DirectTransferThreshold auf einen Wert größer als 8192 festlegen, wird das Framework auf das nächste exakte Vielfache von PAGE_SIZE aufgerundet. Auch hier verwendet das Framework gepufferte E/A für Puffer, die kleiner als der Schwellenwert sind, und direkte E/A für Puffer, die dem Schwellenwert entsprechen oder größer sind.

  • UMDF verwendet direkte E/A nur für Pufferspeicher, der auf einer Speicherseitengrenze beginnt und endet. Wenn der Anfang oder das Ende eines Puffers nicht auf einer Seitengrenze liegt, verwendet UMDF gepufferte E/A-Vorgänge für diesen Teil des Puffers. Anders ausgedrückt: UMDF kann für eine große Datenübertragung, die aus mehreren E/A-Anforderungen besteht, sowohl gepufferte E/A- als auch direkte E/A-E/A-Vorgänge verwenden.

  • Für Geräte-E/A-Steuerungsanforderungen verwendet UMDF direkte E/A-Vorgänge nur, wenn der E/A-Steuerungscode (IOCTL) direkte E/A angibt, und nur, wenn alle UMDF-basierten Treiber des Geräts IWDFDeviceInitialize2:SetIoTypePreference aufgerufen haben, um die direkte Zugriffsmethode anzugeben.

Treiber verwenden denselben Satz von Anforderungsobjektmethoden, um auf Datenpuffer zuzugreifen, unabhängig von der Pufferzugriffsmethode. Daher müssen die meisten Treiber in der Regel nicht wissen, ob UMDF gepufferte E/A- oder direkte E/A-Vorgänge für eine E/A-Anforderung verwendet.

Wie ein Treiber die Zugriffsmethode für eine E/A-Anforderung abrufen kann

In einigen Fällen können Sie die Leistung des Geräts und des Treibers verbessern, wenn die Zugriffsmethode bekannt ist. In solchen Fällen kann Ihr Treiber IWDFIoRequest2::GetEffectiveIoType aufrufen, um die Pufferzugriffsmethode einer E/A-Anforderung abzurufen.

Betrachten Sie beispielsweise ein Gerät mit hohem Durchsatz, das in der Regel direkte E/A verwendet. Da er direkte E/A verwendet, muss der Treiber anwendungsspezifische Parameter in den lokalen Treiberspeicher kopieren, bevor er die Parameter überprüft, um sicherzustellen, dass die Anwendung die Parameter nach der Überprüfung nicht ändert.

Da der Treiber gelegentlich einen Puffer erhält, der gepufferte E/A verwendet, und weil gepufferte E/A-Puffer bereits kopiert wurden, kann die Anwendung die Daten nicht ändern, und der Treiber muss keine Parameter kopieren, bevor sie überprüft werden. Aus diesem Grund sollte der Treiber die Pufferzugriffsmethode jeder Anforderung überprüfen, um zu ermitteln, ob parameter kopiert werden müssen, bevor er sie überprüft.

Verwenden gepufferter E/A-Vorgänge in UMDF-Treibern

Wenn Ihr Treiber gepufferte E/A verwendet, unterscheidet sich das UMDF-Verhalten je nach Anforderungstyp. Für Lese- und Schreibanforderungen erstellt der Treiberhostprozess einen einzelnen Zwischenpuffer, auf den der Treiber zugreifen kann.

Bei Schreibanforderungen überträgt der Treiberhostprozess Eingabeinformationen aus dem Eingabepuffer der aufrufenden Anwendung, bevor der Treiberstapel aufgerufen wird. Treiber lesen in der Regel Eingabeinformationen aus dem Zwischenpuffer und schreiben sie auf das Gerät.

Bei Leseanforderungen lesen Treiber in der Regel Informationen von einem Gerät und speichern es im Zwischenpuffer. Der Treiberhostprozess kopiert die Ausgabedaten aus dem Zwischenpuffer in den Ausgabepuffer der Anwendung.

Für Geräte-E/A-Steuerungsanforderungen erstellt der Treiberhostprozess jedoch zwei separate Puffer, auf die der Treiber zugreifen kann. Beachten Sie, dass sich dies vom Verhalten von WDM- und KMDF-Treibern unterscheidet, bei denen Lese-, Schreib- und Geräte-E/A-Steuerungsanforderungen, die mithilfe gepufferter E/A-E/A gesendet werden, dazu führen, dass der Treiber auf einen einzelnen Zwischenpuffer zugreift. In diesem Fall enthält der Ausgabepuffer zunächst nichts, und der Treiber sollte nicht daraus lesen. Darüber hinaus werden alle Daten, die der Treiber in den Eingabepuffer schreibt, verworfen und nicht an die aufrufende Anwendung zurückgegeben.

Richtlinien zum Auswählen von gepufferten E/A-Vorgängen finden Sie unter WDF_DEVICE_IO_TYPE.

UMDF-Versionen 1.9 und höher können den sofortigen oder verzögerten Abruf von Anforderungspuffern unterstützen. Weitere Informationen finden Sie unter WDF_DEVICE_IO_BUFFER_RETRIEVAL.

Ein Treiber, der den Sofortigen Pufferabrufmodus verwendet, muss IWDFIoRequest::GetInputMemory und IWDFIoRequest::GetOutputMemory verwenden, um auf die Puffer zuzugreifen.

Ein Treiber, der den verzögerten Pufferabrufmodus verwendet, kann auf die Puffer zugreifen, indem er IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer oder IWDFIoRequest2::RetrieveOutputMemory aufruft.

Verwenden von Direct E/O in UMDF-Treibern

Wenn Ihr Treiber direkte E/A verwendet, überprüft der Treiberhostprozess die Barrierefreiheit des Pufferraums, den der Absender der E/A-Anforderung (in der Regel eine Anwendung im Benutzermodus) angegeben hat, sperrt den Pufferspeicher in den physischen Arbeitsspeicher und gewährt dem Treiber dann direkten Zugriff auf den Pufferspeicher.

Richtlinien zur Auswahl direkter E/A-Vorgänge finden Sie unter WDF_DEVICE_IO_TYPE.

Ihr Treiber kann auf die Puffer zugreifen, indem er IWDFIoRequest2::RetrieveInputBuffer, IWDFIoRequest2::RetrieveInputMemory, IWDFIoRequest2::RetrieveOutputBuffer oder IWDFIoRequest2::RetrieveOutputMemory aufruft.

Verwenden weder gepufferter E/A noch direkter E/A in UMDF-Treibern

Die Pufferzugriffsmethode, die weder als gepufferte E/A-Methode noch als direkte E/A-Methode (oder kurz die "weder"-Methode) bezeichnet wird, ermöglicht Treibern den direkten Zugriff auf die Anforderungspufferzeiger einer Anwendung. UMDF-basierte Treiber können diese Zugriffsmethode nicht verwenden.

Die Definitionen einiger Geräte-E/A-Steuerungscodes (IOCTLs) geben jedoch an, dass die Anforderungen die Methode "weder" verwenden. Optional kann UMDF die Pufferzugriffsmethode solcher Geräte-E/A-Steuerungsanforderungen in gepufferte E/A- oder direkte E/A-Vorgänge konvertieren. Führen Sie die folgenden Schritte durch:

  1. Schließen Sie die UmdfMethodNeitherAction-Direktive in einen INF DDInstall-Abschnitt der INF-Datei Ihres Treibers ein. Sie können den Wert der Direktive festlegen, um anzugeben, dass UMDF Geräte-E/A-Steuerungsanforderungen, die die Zugriffsmethode "weder" verwenden, an den Treiber übergeben soll. (Andernfalls schließt UMDF diese E/A-Anforderungen mit einem Fehler status Wert ab.)

  2. Greifen Sie auf die Puffer der E/A-Anforderung zu, indem Sie die Objektmethoden verwenden, die UMDF für gepufferte E/A-Vorgänge oder direkte E/A bereitstellt.

Sie sollten die Unterstützung von IOCTL-Anforderungen aktivieren, die die Methode "weder" verwenden, wenn Sie sicher sind, dass UMDF die Zugriffsmethode in gepufferte E/A- oder direkte E/A-Vorgänge konvertieren kann. Wenn die IOCTL beispielsweise eine benutzerdefinierte Anforderung angibt, die nicht den Unter Pufferbeschreibungen für E/A-Steuercodes beschriebenen Pufferspezifikationsregeln entspricht, kann UMDF die Puffer nicht konvertieren.