Freigeben über


Beispiel für die Toaster-Treiberprogrammiertour

Dieses Thema enthält eine exemplarische Code-Vorgehensweise des Toaster-Beispiels, das Kernel-Mode Driver Framework (KMDF) und User-Mode Driver Framework (UMDF)-Treiber für Lernzwecke enthält.

Anwendungen

Das Beispiel umfasst Anwendungen, die mit dem Toaster-Bustreiber und Funktionstreiber interagieren. Diese Anwendungen funktionieren sowohl mit KMDF- als auch mit UMDF-Toasterversionen.

  • Enum.exe ist ein Benutzermodus-Enumerator, eine einfache Konsolenanwendung. Da der Toasterbus kein physischer Bus ist, können Sie diese Anwendung verwenden, um zu veranlassen, dass der Bustreiber Geräte ein- und aus dem System ausgibt. Geben Sie Enum.exe für Nutzungstipps ein.
  • Toast.exe: Dies ist eine Konsolenanwendung im Benutzermodus zum Steuern des Toasters. Diese Anwendung listet Toastergeräte auf, öffnet das letzte aufgezählte Gerät und sendet eine Leseanforderung an das Gerät.
  • Notify.exe: Diese GUI-Anwendung kombiniert die Funktionalität von Enum.exe und toast.exe und zeigt auch, wie PnP-Benachrichtigungen im Benutzermodus behandelt werden. Sie können auch Notify.exe verwenden, um eine andere Hardware-ID (als die Standard-Toastergeräte-ID) anzugeben, damit ein anderer Treiber als Funktionstreiber geladen wird.

KMDF-Bustreiber

Der KMDF-Bustreiber verwaltet den Toaster-Buscontroller, zählt eingesteckte Geräte auf und führt die Energieverwaltung auf Busebene aus. Der Bustreiber unterstützt die D0- und D3-Leistungszustände. Es verfügt auch über eine WMI-Schnittstelle. Dieses Verzeichnis enthält zwei Unterverzeichnisse, die zwei unterschiedliche Implementierungen des Toaster-Bustreibers anzeigen.

  • Statisch

    Die statische Version des Bustreibers zeigt, wie untergeordnete Geräte mithilfe einer statischen untergeordneten Liste aufgelistet werden, eine pro Gerät, die vom Framework bereitgestellt wird.

    Die statische Enumeration ermöglicht es einem Treiber, das Vorhandensein von Geräten während der Initialisierung zu erkennen und zu melden, wobei es nur eingeschränkt möglich ist, nachfolgende Änderungen an der Systemkonfiguration zu melden.

    Bustreiber können eine statische Enumeration verwenden, wenn die Anzahl und der Typ der Geräte oder funktionalen Untereinheiten vorab festgelegt und dauerhaft ist und nicht von der Konfiguration des Systems abhängt, auf dem der Treiber ausgeführt wird.

    Beispielsweise kann der Treiber einer Soundkarte als Bustreiber fungieren und separate physische Geräteobjekte (PDOs) für jede der Funktionen der Karte erstellen, z. B. MIDI, Audio und Joystick.

    Um ein Untergeordnetes aufzulisten, muss der Busfahrer folgendes unternehmen:

    1. Ruft WdfPdoInitAllocate auf, um eine WDFDEVICE_INIT-Struktur zu erhalten.

    2. Initialisiert die WDFDEVICE_INIT-Struktur .

    3. Rufen Sie WdfDeviceCreate auf , um ein Framework-Geräteobjekt zu erstellen, das ein PDO darstellt.

    Nach dem Aufruf von WdfDeviceCreate ruft der Treiber WdfFdoAddStaticChild auf, um das untergeordnete Gerät der untergeordneten Liste hinzuzufügen.

    Da Treiber nur statische untergeordnete Listen für Gerätekonfigurationen verwenden sollten, die vorab festgelegt und dauerhaft sind, ändert ein Treiber in der Regel keine statische untergeordnete Liste, nachdem sie erstellt wurde. Wenn der Treiber feststellt, dass auf ein untergeordnetes Gerät nicht mehr zugegriffen werden kann, kann der Treiber WdfPdoMarkMissing aufrufen. (Wenn auf ein untergeordnetes Gerät zugegriffen werden kann, aber nicht reagiert, sollte der Treiber das Failed-Element der WDF_DEVICE_STATE-Struktur auf WdfTrue festlegen und dann WdfDeviceSetDeviceState aufrufen.)

    Um untergeordnete Geräte bei jedem Start des Bustreibers statisch aufzulisten, konfigurieren Sie diesen Wert über die Toaster Bus Inf-Datei. Die maximale Anzahl untergeordneter Geräte, die mit dieser Registrierungseinstellung aufgezählt werden können, ist 10.

    [ToasterStatBus_Device.NT.HW]
    AddReg=ToasterStatBus_Device.NT.AddReg
    
    [ToasterStatBus_Device.NT.AddReg]
    HKR,,NumberOfToasters,0x10001,2
    
  • Dynamisch

    Die dynamische Version des Bustreibers zeigt, wie untergeordnete Geräte mithilfe von untergeordneten Listenobjekten aufgelistet werden.

    Die dynamische Enumeration ermöglicht es einem Treiber, Änderungen an der Anzahl und dem Typ von Geräten zu erkennen und zu melden, die während der Systemausführung mit dem System verbunden sind.

    Bustreiber müssen eine dynamische Enumeration verwenden, wenn die Anzahl oder die Typen von Geräten, die mit dem übergeordneten Gerät verbunden sind, von der Konfiguration eines Systems abhängen. Einige dieser Geräte sind möglicherweise immer mit dem System verbunden, und einige werden möglicherweise ein- und getrennt, während das System ausgeführt wird.

    Beispielsweise sind die Anzahl und der Typ der Geräte, die an den PCI-Bus eines Systems angeschlossen sind, systemabhängig, aber sie sind dauerhaft, es sei denn, ein Benutzer schaltet die Stromversorgung aus, öffnet das Gehäuse und fügt ein Gerät mithilfe eines Schraubenziehers hinzu oder entfernt es. Andererseits kann ein Benutzer USB-Geräte hinzufügen oder entfernen, indem er ein Kabel ein- oder aussteckt, während das System ausgeführt wird.

    Jedes Mal, wenn ein Bustreiber ein untergeordnetes Gerät identifiziert, muss er die Beschreibung des untergeordneten Geräts zu einer untergeordneten Liste hinzufügen. Der Treiber kann entweder die standardmäßige untergeordnete Liste des vom Framework bereitgestellten Geräts verwenden, indem er WdfFdoGetDefaultChildList aufruft, oder er kann zusätzliche untergeordnete Listen zum Gruppieren von untergeordneten Elementen erstellen, indem er WdfChildListCreate aufruft. In diesem Beispiel wird die untergeordnete Standardliste verwendet. Eine untergeordnete Beschreibung besteht aus einer erforderlichen Identifikationsbeschreibung und einer optionalen Adressbeschreibung.

    Begriff BESCHREIBUNG

    Identifikationsbeschreibung

    Eine Identifikationsbeschreibung ist eine Struktur, die Informationen enthält, die jedes Gerät eindeutig identifiziert, das der Treiber aufzählt. Der Treiber definiert diese Struktur, sein erstes Element muss jedoch eine WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER-Struktur sein.

    Adressbeschreibung

    Eine Adressbeschreibung ist eine Struktur, die Informationen enthält, die der Treiber benötigt, damit er auf das Gerät auf seinem Bus zugreifen kann, wenn sich die Informationen ändern können, während das Gerät angeschlossen ist. Der Treiber definiert diese Struktur, sein erstes Element muss jedoch eine WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER-Struktur sein. Adressbeschreibungen sind optional. In diesem Beispiel werden keine Adressbeschreibungen verwendet.

Um untergeordnete Elemente zu einer untergeordneten Liste hinzuzufügen, ruft der Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent für jedes untergeordnete Gerät auf, das er findet. Dieser Aufruf informiert das Framework darüber, dass ein Treiber ein untergeordnetes Gerät ermittelt hat, das mit einem übergeordneten Gerät verbunden ist. Wenn Ihr Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent aufruft, liefert er eine Identifikationsbeschreibung und optional eine Adressbeschreibung.

Nachdem der Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent aufgerufen hat, um ein neues Gerät zu melden, informiert das Framework den PnP-Manager darüber, dass das neue Gerät vorhanden ist. Der PnP-Manager erstellt dann einen Gerätestapel und einen Treiberstapel für das neue Gerät. Im Rahmen dieses Prozesses ruft das Framework die Rückruffunktion EvtChildListCreateDevice des Bustreibers auf. Diese Rückruffunktion muss WdfDeviceCreate aufrufen, um ein PDO für das neue Gerät zu erstellen.

Um ein fehlendes untergeordnetes Gerät zu melden, ruft dieser Treiber WdfChildListUpdateChildDescriptionAsMissing auf. Weitere Informationen zur dynamischen Enumeration finden Sie in der Frameworkdokumentation.

KMDF-Funktionstreiber

Der Funktionstreiber verfügt über zwei verschiedene Versionen: wdfsimple und wdffeatured. Die beiden Versionen des Funktionstreibers verwenden eine gemeinsame Headerdatei im freigegebenen Verzeichnis.

  • WdfSimple

    In dieser Version verarbeitet der Treiber keine PnP- und Power-Ereignisse, sondern basiert stattdessen auf der Standardunterstützung des Frameworks für diese Ereignisse. Eine Anwendung, z. B. notify.exe, kann diesen Treiber verwenden, um die vom Treiber registrierte Geräteschnittstelle zu öffnen und Lese-, Schreib- oder IOCTL-Anforderungen zu senden.

  • WdfFeatured

    Diese Version zeigt, wie Sie sich für PNP- und Power-Ereignisse registrieren, Dateianforderungen erstellen und schließen, WMI-Set- und Abfrageereignisse behandeln und WMI-Benachrichtigungsereignisse auslösen. Als Besitzer einer Energierichtlinie registriert er sich auch für Benachrichtigungen im Leerlauf, sodass das Gerät in den Energiesparmodus versetzt werden kann, wenn keine E/A-Aktivität vorhanden ist.

KMDF-Filtertreiber

Dieses Verzeichnis enthält Quellcode für zwei Filtertreiber. Das generische Beispiel ist ein einfacher Passthru-Filtertreiber. Das SideBand zeigt, wie eine Sideband-ioctl-Schnittstelle für eine Anwendung mithilfe des Steuerelement-Geräteobjekts bereitgestellt wird. Diese private Schnittstelle ermöglicht es der Anwendung, direkt mit dem Filtertreiber zu kommunizieren. Umgehung des funktionalen Gerätestapels, an den der Filter angefügt ist. Das SideBand-Beispiel zeigt auch, wie eine Auflistung von Geräteobjekten implementiert wird, wenn der Treiber Anforderungen für mehrere Geräte verarbeitet. Sie können diese Filter auf einem vorhandenen Toastergerät installieren, indem Sie filter.inf verwenden.

KMDF Toastmon

In diesem Beispiel wird veranschaulicht, wie Sie ein Gerät öffnen und E/A im Kernelmodus mithilfe von Remote-E/A-Zielschnittstellen ausführen. In diesem Beispiel wird eine PnP-Benachrichtigungsrückrufroutine für die Toaster-Schnittstellenklasse registriert, indem IoRegisterPlugPlayNotification aufgerufen wird. Wenn ein Toastergerät angeschlossen ist, ruft der PnP-Manager den Rückruf auf. Im Rückruf wird in diesem Beispiel ein Remoteziel erstellt und das Gerät mithilfe des symbolischen Links in den Rückrufdaten geöffnet.

Außerdem wird in diesem Beispiel ein passiver Timer verwendet, um asynchrones Lesen und Schreiben auf dem Zielgerät zu veranschaulichen. Außerdem wird gezeigt, wie Sie auf eine Geräteänderungsbenachrichtigung reagieren, indem Sie EvtIoTargetQueryRemove/EvtIoTargetRemoveCanceled/EvtIoTargetRemoveComplete für das E/A-Zielobjekt registrieren. Sie können dieses Verfahren verwenden, wenn Ihr Treiber mit einem anderen Gerät spricht, das ihr Treiber nicht steuert. Sie installieren diesen Treiber als root-enumeriertes Gerät mit Wdftoastmon.inf. Verwenden Sie die gleichen Schritte für die Installation wie der Toaster-Bustreiber.

UMDF-Funktionstreiber

Mit dem WUDFToaster-Treiber kann eine Benutzeranwendung (Popup/notify.exe) die vom Treiber registrierte Geräteschnittstelle öffnen und Lese-, Schreib- oder IOCTL-Anforderungen senden. Dieses Treiberbeispiel zeigt auch, wie Sie sich für PnP- und Power-Ereignisse registrieren, den Besitz von Energierichtlinien festlegen und E/A-Anforderungen behandeln. Dies ist ein minimales Treiberbeispiel, das nicht für die Verwendung in einer Produktionsumgebung vorgesehen ist.

Sie können den WUDF-Toaster in Verbindung mit dem KMDF-Toastmonbeispiel verwenden, um den Clientzugriff im Kernelmodus auf einen Benutzermodustreiber mithilfe von Remote-E/A-Zielen zu veranschauliche.

Fügen Sie dazu die folgende Zeile hinzu. WDF-Abschnitt des INF für diesen UMDF-Treiber: UmdfKernelModeClientPolicy = AllowKernelModeClients

Testen des UMDF-Toasters

  1. Verwenden Sie Toast.exe-, Notify.exe- oder Enum.exe-Anwendungen.
  2. Installieren Sie den KMDF Toastmon-Treiber. Lassen Sie Kernelmodusclients benutzermodustreiber zu, wie zuvor beschrieben. Installieren Sie WUDFToaster.dll. Verwenden Sie Traceview.exe, um die Anforderungen anzuzeigen, die von Toastmon an den UMDF Toaster gesendet werden.

UMDF-Toastmonübersicht

Dieses Beispiel ist eine UMDF-Version des KMDF ToastMon-Beispiels.

UMDF Toastmon veranschaulicht die Verwendung von UMDF zum Schreiben eines minimalen Treibers mit dem User-Mode Driver Framework und zeigt bewährte Methoden an. Der Treiber wird erfolgreich auf ein Gerät geladen (entweder aufgezählte Stammdaten oder ein echtes Hardwaregerät), verfügt jedoch über die minimale PnP-Funktionalität und unterstützt nicht den Empfang von E/A-Vorgängen.

Toastmon soll als Lerntool für andere UMDF-Treiber dienen, die Sie möglicherweise schreiben.