Utilisation de minuteurs

Cette rubrique explique comment utiliser la prise en charge intégrée du minuteur de l’infrastructure. Il s’applique à la fois aux pilotes KMDF (Kernel-Mode Driver Framework) ainsi qu’aux pilotes UMDF (User-Mode Driver Framework) à partir de la version 2.

L’infrastructure fournit un objet minuteur qui permet aux pilotes de créer des minuteurs. Une fois qu’un pilote a créé un objet minuteur et a démarré l’horloge du minuteur, l’infrastructure appelle une fonction de rappel fournie par le pilote après l’expiration d’une durée spécifiée. Si vous le souhaitez, votre pilote peut configurer le minuteur afin que l’infrastructure appelle la fonction de rappel à plusieurs reprises, chaque fois qu’une durée spécifiée s’est écoulée.

Pour créer un objet de minuteur d’infrastructure, votre pilote doit appeler la méthode WdfTimerCreate . Cette méthode inscrit une fonction de rappel EvtTimerFunc et un intervalle de temps périodique. Si vous souhaitez que l’infrastructure n’appelle la fonction de rappel qu’une seule fois, votre pilote spécifie zéro pour l’intervalle de temps périodique.

En règle générale, vous connaissez le nombre de minuteurs dont votre pilote aura besoin pour chaque appareil. Par conséquent, le pilote peut créer des objets minuteur en appelant WdfTimerCreate dans sa fonction de rappel EvtDriverDeviceAdd , et il peut stocker les handles d’objet minuteur dans l’espace de contexte d’un objet d’appareil ou de file d’attente.

Pour démarrer le minuteur, votre pilote appelle WdfTimerStart, en passant un « délai d’échéance ». L’infrastructure démarre l’horloge du minuteur et appelle la fonction de rappel EvtTimerFunc lorsque la durée spécifiée est écoulée.

Si le pilote a fourni un intervalle de temps périodique lorsqu’il a appelé WdfTimerCreate, le minuteur est appelé minuteur périodique. L’horloge d’un minuteur périodique continue de s’exécuter après l’expiration du « délai » initial, et l’infrastructure appelle la fonction de rappel du pilote à plusieurs reprises, chaque fois que l’intervalle de temps périodique s’est écoulé. Les minuteurs périodiques ne démarrent pas automatiquement. Comme les minuteurs non périodiques, le pilote doit toujours appeler WdfTimerStart après avoir créé le minuteur pour le démarrer la première fois.

Un pilote peut appeler WdfTimerStart à partir de sa fonction de rappel EvtTimerFunc afin de redémarrer un minuteur non périodique après son expiration.

Pour arrêter un minuteur, le pilote peut appeler WdfTimerStop. Votre pilote peut réutiliser les minuteurs en les démarrant et en les arrêtant à plusieurs reprises.

Lorsque votre pilote crée un objet minuteur, il doit spécifier un objet parent. L’infrastructure arrête le minuteur et supprime l’objet minuteur lorsque le parent est supprimé. Pour obtenir l’objet parent d’un objet minuteur, votre pilote peut appeler WdfTimerGetParentObject.

Dans les versions KMDF antérieures à la version 1.9, vous ne pouvez pas facilement utiliser des objets de minuteur si vous souhaitez que toutes les fonctions de rappel de votre pilote s’exécutent à IRQL = PASSIVE_LEVEL. L’infrastructure implémente la fonction de rappel EvtTimerFunc de l’objet minuteur en tant qu’appel de procédure différée (DPC) appelé à IRQL = DISPATCH_LEVEL. Par conséquent, si vous souhaitez que le code d’expiration de votre minuteur s’exécute à PASSIVE_LEVEL la fonction de rappel EvtTimerFunc doit mettre en file d’attente un élément de travail qui s’exécute à PASSIVE_LEVEL.

Dans KMDF versions 1.9 et ultérieures, vous pouvez créer des minuteurs de niveau passif, qui sont des minuteurs qui s’exécutent à PASSIVE_LEVEL. Pour créer un minuteur de niveau passif, spécifiez le niveau d’exécution WdfExecutionLevelPassive lorsque votre pilote appelle WdfTimerCreate. Par conséquent, l’infrastructure implémente des fonctions de rappel EvtTimerFunc en tant qu’éléments de travail qui s’exécutent à PASSIVE_LEVEL. Notez que les minuteurs passifs ne peuvent pas être des minuteurs périodiques.

À compter de la version 2.0 d’UMDF, l’infrastructure implémente les fonctions de rappel EvtTimerFunc de l’objet de minuteur en tant que threads de travail à partir du pool de threads en mode utilisateur. Par conséquent, les fonctions de rappel du minuteur d’un pilote UMDF s’exécutent toujours à PASSIVE_LEVEL.

Pas de minuteurs de veille

L’efficacité énergétique du système est réduite par les minuteurs qui provoquent à plusieurs reprises la reprise du système à partir d’états de faible puissance. Une façon d’améliorer l’autonomie de la batterie consiste à retarder les opérations périodiques non critiques plutôt que de réveiller le système. À partir de Windows 8.1, vous ne pouvez utiliser aucun minuteur de veille pour effectuer de telles opérations non critiques dans un pilote KMDF ou UMDF. Un minuteur sans éveil ne réveille pas le système s’il expire alors que le système est dans un état de faible consommation d’énergie. Au lieu de cela, l’infrastructure appelle la fonction de rappel EvtTimerFunc du pilote la prochaine fois que le système est entièrement activé, S0.

Aucun minuteur de veille n’est disponible à partir de KMDF version 1.13 et UMDF version 2.0.

Pour créer un minuteur sans éveil, définissez le membre IntolérableDelay de WDF_TIMER_CONFIG sur IntolérableDelayUnlimited.

Pour plus d’informations sur l’absence de minuteurs de veille, consultez Minuteurs sans veille.

Minuteurs haute résolution

Les minuteurs d’infrastructure standard ont une précision qui correspond à l’intervalle de graduation de l’horloge système, qui est par défaut de 15,6 millisecondes. À partir de Windows 8.1, vous pouvez créer des minuteurs haute résolution. Un minuteur haute résolution a une précision d’une milliseconde. Vous pouvez utiliser un minuteur haute résolution pour une opération critique qui nécessite un délai d’expiration précis et prévisible. En raison de l’entretien fréquent qu’il nécessite, un minuteur à haute résolution peut entraîner une diminution de l’autonomie de la batterie.

Les minuteurs haute résolution sont disponibles uniquement pour les pilotes KMDF, à compter de KMDF version 1.13.

Pour créer un minuteur haute résolution, définissez le membre UseHighResolutionTimer de WDF_TIMER_CONFIG sur WdfTrue, puis ajustez la valeur Period à la résolution souhaitée.

Le tableau suivant présente des exemples de comportement du minuteur en fonction des différentes valeurs que le pilote fournit pour Period. Ces exemples supposent que l’intervalle de graduation de l’horloge système est de 15 millisecondes.

Point, en ms Minuteur standard Minuteur haute résolution

10

Le minuteur expire entre 0 milliseconde et 25 millisecondes.

Le minuteur expire dès que possible après 10 millisecondes.

16

Le minuteur expire entre 15 millisecondes et 30 millisecondes.

Le minuteur expire dès que possible après 16 millisecondes.

Pour plus d’informations sur les minuteurs haute résolution, consultez Minuteurs haute résolution.

Pour plus d’informations sur la façon dont la précision du minuteur est liée à la granularité de l’horloge système, consultez Précision du minuteur.