Uso de temporizadores
En este tema se describe cómo usar la compatibilidad del temporizador integrado del marco. Se aplica tanto a los controladores Kernel-Mode Driver Framework (KMDF), como a los controladores de User-Mode Driver Framework (UMDF) a partir de la versión 2.
El marco proporciona un objeto de temporizador que permite a los controladores crear temporizadores. Una vez que un controlador crea un objeto de temporizador e inicia el reloj del temporizador, el marco llama a una función de devolución de llamada proporcionada por el controlador después de que haya transcurrido una cantidad de tiempo especificada. Opcionalmente, el controlador puede configurar el temporizador para que el marco llame repetidamente a la función de devolución de llamada, siempre que haya transcurrido una cantidad de tiempo especificada.
Para crear un objeto de temporizador de marco, el controlador debe llamar al método WdfTimerCreate . Este método registra una función de devolución de llamada EvtTimerFunc y un intervalo de tiempo periódico. Si desea que el marco llame a la función de devolución de llamada una sola vez, el controlador especifica cero para el intervalo de tiempo periódico.
Normalmente, sabrá el número de temporizadores que el controlador necesitará para cada dispositivo. Por lo tanto, el controlador puede crear objetos de temporizador llamando a WdfTimerCreate en su función de devolución de llamada EvtDriverDeviceAdd y puede almacenar identificadores de objeto de temporizador en el espacio de contexto de un objeto de dispositivo o cola.
Para iniciar el temporizador, el controlador llama a WdfTimerStart, pasando un "tiempo de vencimiento". El marco inicia el reloj del temporizador y llama a la función de devolución de llamada EvtTimerFunc cuando ha transcurrido la cantidad de tiempo especificada.
Si el controlador proporcionó un intervalo de tiempo periódico al llamar a WdfTimerCreate, el temporizador se conoce como temporizador periódico. El reloj de un temporizador periódico continúa ejecutándose después de que haya transcurrido el "tiempo de vencimiento" inicial y el marco llama repetidamente a la función de devolución de llamada del controlador, siempre que haya transcurrido el intervalo de tiempo periódico. Los temporizadores periódicos no se inician automáticamente. Al igual que los temporizadores no periódicos, el controlador debe seguir llamando a WdfTimerStart después de crear el temporizador para iniciarlo la primera vez.
Un controlador puede llamar a WdfTimerStart desde su función de devolución de llamada EvtTimerFunc para reiniciar un temporizador no periódico después de que expire.
Para detener un temporizador, el controlador puede llamar a WdfTimerStop. El controlador puede reutilizar temporizadores iniciando y deteniendolos repetidamente.
Cuando el controlador crea un objeto de temporizador, debe especificar un objeto primario. El marco detiene el temporizador y elimina el objeto de temporizador cuando se elimina el elemento primario. Para obtener el objeto primario de un objeto del temporizador, el controlador puede llamar a WdfTimerGetParentObject.
En las versiones de KMDF anteriores a la versión 1.9, no puede usar fácilmente objetos de temporizador si desea que todas las funciones de devolución de llamada del controlador se ejecuten en IRQL = PASSIVE_LEVEL. El marco implementa la función de devolución de llamada EvtTimerFunc del objeto de temporizador como una llamada de procedimiento diferida (DPC) a la que se llama en IRQL = DISPATCH_LEVEL. Por lo tanto, si desea que el código de expiración del temporizador se ejecute en PASSIVE_LEVEL la función de devolución de llamada EvtTimerFunc debe poner en cola un elemento de trabajo que se ejecute en PASSIVE_LEVEL.
En las versiones 1.9 y posteriores de KMDF, puede crear temporizadores de nivel pasivo, que son temporizadores que se ejecutan en PASSIVE_LEVEL. Para crear un temporizador de nivel pasivo, especifique el nivel de ejecución WdfExecutionLevelPassive cuando el controlador llama a WdfTimerCreate. Como resultado, el marco implementa las funciones de devolución de llamada EvtTimerFunc como elementos de trabajo que se ejecutan en PASSIVE_LEVEL. Tenga en cuenta que los temporizadores de nivel pasivo no pueden ser temporizadores periódicos.
A partir de la versión 2.0 de UMDF, el marco implementa las funciones de devolución de llamada EvtTimerFunc del objeto de temporizador como subprocesos de trabajo del grupo de subprocesos en modo de usuario. Como resultado, las funciones de devolución de llamada del temporizador del controlador UMDF siempre se ejecutan en PASSIVE_LEVEL.
Sin temporizadores de reactivación
La eficiencia energética del sistema se reduce por temporizadores que provocan repetidamente que el sistema se reanude desde estados de baja potencia. Una manera de mejorar la duración de la batería es retrasar las operaciones periódicas no críticas en lugar de despertar el sistema. A partir de Windows 8.1, no puede usar temporizadores de reactivación para realizar estas operaciones no críticas en un controlador KMDF o UMDF. Un temporizador de reactivación no activa el sistema si expira mientras el sistema está en estado de bajo consumo. En su lugar, el marco llama a la función de devolución de llamada EvtTimerFunc del controlador la próxima vez que el sistema esté totalmente activado, estado S0.
No hay temporizadores de reactivación disponibles a partir de la versión 1.13 de KMDF y la versión 2.0 de UMDF.
Para crear un temporizador sin reactivación, establezca el miembro TolerableDelay de WDF_TIMER_CONFIG en TolerableDelayUnlimited.
Para obtener más información sobre los temporizadores de reactivación, vea No-Wake Timers.
Temporizadores de alta resolución
Los temporizadores del marco estándar tienen una precisión que coincide con el intervalo de graduación del reloj del sistema, que es de forma predeterminada de 15,6 milisegundos. A partir de Windows 8.1, puede crear temporizadores de alta resolución. Un temporizador de alta resolución tiene una precisión de un milisegundo. Puede usar un temporizador de alta resolución para una operación crítica que requiera un tiempo de expiración preciso y predecible. Como resultado del mantenimiento frecuente que requiere, un temporizador de alta resolución puede dar lugar a una disminución de la duración de la batería.
Los temporizadores de alta resolución solo están disponibles para los controladores KMDF, a partir de la versión 1.13 de KMDF.
Para crear un temporizador de alta resolución, establezca el miembro UseHighResolutionTimer de WDF_TIMER_CONFIGen WdfTrue y, a continuación, ajuste el valor Period a la resolución deseada.
En la tabla siguiente se muestran ejemplos de comportamiento del temporizador en función de los distintos valores que proporciona el controlador para Period. En estos ejemplos se supone que el intervalo de graduación del reloj del sistema es de 15 milisegundos.
Período, en ms | Temporizador estándar | Temporizador de alta resolución |
---|---|---|
10 |
El temporizador expira entre 0 milisegundos y 25 milisegundos. |
El temporizador expira tan pronto como sea posible después de 10 milisegundos. |
16 |
El temporizador expira entre 15 milisegundos y 30 milisegundos. |
El temporizador expira tan pronto como sea posible después de 16 milisegundos. |
Para obtener más información sobre los temporizadores de alta resolución, consulte Temporizadores de alta resolución.
Para obtener más información sobre cómo la precisión del temporizador está relacionada con la granularidad del reloj del sistema, consulte Precisión del temporizador.