Verwenden von Timern
In diesem Thema wird beschrieben, wie Sie die integrierte Timerunterstützung des Frameworks verwenden. Es gilt sowohl für Kernel-Mode Driver Framework (KMDF)-Treiber als auch für User-Mode Driver Framework (UMDF)-Treiber ab Version 2.
Das Framework stellt ein Timerobjekt bereit , mit dem Treiber Timer erstellen können. Nachdem ein Treiber ein Timerobjekt erstellt und die Uhr des Timers startet, ruft das Framework eine vom Treiber bereitgestellte Rückruffunktion auf, nachdem eine bestimmte Zeit verstrichen ist. Optional kann Ihr Treiber den Timer so einrichten, dass das Framework die Rückruffunktion wiederholt aufruft, wenn eine bestimmte Zeit verstrichen ist.
Um ein Framework-Timerobjekt zu erstellen, muss Ihr Treiber die WdfTimerCreate-Methode aufrufen. Diese Methode registriert eine EvtTimerFunc-Rückruffunktion und ein periodisches Zeitintervall. Wenn das Framework die Rückruffunktion nur einmal aufrufen soll, gibt Ihr Treiber null für das periodische Zeitintervall an.
In der Regel kennen Sie die Anzahl von Timern, die Ihr Treiber für jedes Gerät benötigt. Daher kann der Treiber Zeitgeberobjekte erstellen, indem er WdfTimerCreate in seiner Rückruffunktion EvtDriverDeviceAdd aufruft , und er kann Timerobjekthandles im Kontextbereich eines Geräte- oder Warteschlangenobjekts speichern.
Um den Timer zu starten, ruft Ihr Treiber WdfTimerStart an und übergibt eine "Fälligkeitszeit". Das Framework startet die Zeituhr des Timers und ruft die EvtTimerFunc-Rückruffunktion auf, wenn die angegebene Zeit verstrichen ist.
Wenn der Treiber beim Aufrufen von WdfTimerCreate ein periodisches Zeitintervall angegeben hat, wird der Timer als periodischer Timer bezeichnet. Die Uhr eines periodischen Timers wird weiterhin ausgeführt, nachdem die anfängliche "Fälligkeitszeit" abgelaufen ist, und das Framework ruft die Rückruffunktion des Treibers wiederholt auf, wenn das periodische Zeitintervall verstrichen ist. Regelmäßige Timer werden nicht automatisch gestartet. Wie nicht periodische Timer muss der Treiber auch nach dem Erstellen des Timers weiterhin WdfTimerStart aufrufen, um ihn beim ersten Starten zu starten.
Ein Treiber kann WdfTimerStart über seine EvtTimerFunc-Rückruffunktion aufrufen, um einen nicht periodischen Timer nach ablaufen zu starten.
Um einen Timer anzuhalten, kann der Treiber WdfTimerStop aufrufen. Ihr Treiber kann Timer wiederverwenden, indem sie wiederholt gestartet und beendet werden.
Wenn Ihr Treiber ein Timerobjekt erstellt, muss er ein übergeordnetes Objekt angeben. Das Framework beendet den Timer und löscht das Timerobjekt, wenn das übergeordnete Objekt gelöscht wird. Um das übergeordnete Objekt eines Zeitgeberobjekts abzurufen, kann Ihr Treiber WdfTimerGetParentObject aufrufen.
In KMDF-Versionen vor Version 1.9 können Sie Timerobjekte nicht einfach verwenden, wenn alle Rückruffunktionen Ihres Treibers unter IRQL = PASSIVE_LEVEL ausgeführt werden sollen. Das Framework implementiert die EvtTimerFunc-Rückruffunktion des Zeitgeberobjekts als verzögerten Prozeduraufruf (DPC), der unter IRQL = DISPATCH_LEVEL aufgerufen wird. Wenn der Ablaufcode des Timers bei PASSIVE_LEVEL ausgeführt werden soll, muss die Rückruffunktion EvtTimerFunc ein Arbeitselement in die Warteschlange stellen, das bei PASSIVE_LEVEL ausgeführt wird.
In KMDF-Versionen 1.9 und höher können Sie Timer auf passiver Ebene erstellen, bei denen es sich um Timer handelt, die mit PASSIVE_LEVEL ausgeführt werden. Um einen Timer auf passiver Ebene zu erstellen, geben Sie die WdfExecutionLevelPassive-Ausführungsebene an, wenn Ihr Treiber WdfTimerCreate aufruft. Daher implementiert das Framework EvtTimerFunc-Rückruffunktionen als Arbeitselemente, die bei PASSIVE_LEVEL ausgeführt werden. Beachten Sie, dass Zeitgeber auf passiver Ebene keine regelmäßigen Timer sein können.
Ab UMDF Version 2.0 implementiert das Framework die EvtTimerFunc-Rückruffunktionen des Zeitgeberobjekts als Workerthreads aus dem Threadpool im Benutzermodus. Daher werden die Timerrückruffunktionen eines UMDF-Treibers immer PASSIVE_LEVEL ausgeführt.
Keine Wake-Timer
Die Energieeffizienz des Systems wird durch Timer verringert, die wiederholt dazu führen, dass das System aus Zuständen mit geringer Leistung wieder aufgenommen wird. Eine Möglichkeit, die Akkulaufzeit zu verbessern, besteht darin, nicht kritische periodische Vorgänge zu verzögern, anstatt das System aufzuwecken. Ab Windows 8.1 können Sie keine Aktivierungszeitgeber verwenden, um solche nicht kritischen Vorgänge in einem KMDF- oder UMDF-Treiber auszuführen. Ein Timer ohne Aktivierung aktiviert das System nicht, wenn es abläuft, während sich das System in einem Zustand mit geringer Leistung befindet. Stattdessen ruft das Framework die EvtTimerFunc-Rückruffunktion des Treibers auf, wenn sich das System das nächste Mal im vollständig aktivierten S0-Zustand befindet.
Ab KMDF-Version 1.13 und UMDF-Version 2.0 sind keine Aktivierungszeitgeber verfügbar.
Um einen Timer ohne Aktivierung zu erstellen, legen Sie den TolerableDelay-Member von WDF_TIMER_CONFIG auf TolerableDelayUnlimited fest.
Weitere Informationen zu keinen Aktivierungszeitgebern finden Sie unter No-Wake Timer.
Hochauflösende Timer
Standardframeworktimer weisen eine Genauigkeit auf, die dem Tickintervall der Systemuhr entspricht, das standardmäßig 15,6 Millisekunden beträgt. Ab Windows 8.1 können Sie hochauflösende Timer erstellen. Ein hochauflösender Timer hat eine Genauigkeit von einer Millisekunde. Sie können einen hochauflösenden Timer für einen kritischen Vorgang verwenden, der eine präzise, vorhersagbare Ablaufzeit erfordert. Aufgrund der häufig benötigten Wartung kann ein hochauflösender Timer zu einer verringerten Akkulaufzeit führen.
Hochauflösende Timer sind ab KMDF-Version 1.13 nur für KMDF-Treiber verfügbar.
Um einen hochauflösenden Timer zu erstellen, legen Sie den UseHighResolutionTimer-Member von WDF_TIMER_CONFIG auf WdfTrue fest, und passen Sie dann den Wert Period auf die gewünschte Auflösung an.
Die folgende Tabelle zeigt Beispiele für das Timerverhalten, das auf verschiedenen Werten basiert, die der Treiber für Period bereitstellt. In diesen Beispielen wird davon ausgegangen, dass das Taktintervall der Systemuhr 15 Millisekunden beträgt.
Punkt, in ms | Standard-Timer | Hochauflösender Timer |
---|---|---|
10 |
Der Timer läuft zwischen 0 Millisekunden und 25 Millisekunden ab. |
Der Timer läuft so bald wie möglich nach 10 Millisekunden ab. |
16 |
Der Timer läuft zwischen 15 Millisekunden und 30 Millisekunden ab. |
Der Timer läuft so bald wie möglich nach 16 Millisekunden ab. |
Weitere Informationen zu hochauflösenden Timern finden Sie unter Hochauflösende Timer.
Weitere Informationen dazu, wie die Timergenauigkeit mit der Granularität der Systemuhr zusammenhängt, finden Sie unter TimerGenauigkeit.