Registro y puesta en cola de una rutina CustomTimerDpc

Un controlador puede registrar una rutina CustomTimerDpc llamando a las siguientes rutinas, normalmente desde su rutina AddDevice :

  1. KeInitializeDpc para registrar su rutina

  2. KeInitializeTimer o KeInitializeTimerEx para configurar un objeto de temporizador

Posteriormente, el controlador puede llamar a KeSetTimer o KeSetTimerEx para especificar una hora de expiración y agregar el objeto de temporizador a la cola del temporizador del sistema. Cuando se alcanza la hora de expiración, el sistema pone en cola el objeto de temporizador y llama a la rutina CustomTimerDpc . En la ilustración siguiente se muestran estas llamadas.

diagrama que ilustra el uso de objetos timer y dpc para una rutina customtimerdpc.

Como se muestra en la ilustración anterior, el controlador debe proporcionar almacenamiento para un objeto DPC y un objeto de temporizador. La mayoría de los controladores proporcionan el almacenamiento para estos objetos en una extensión de dispositivo o en otra memoria residente asignada por el controlador.

En la llamada a KeSetTimer, el controlador pasa punteros a los objetos Dpc y Timer , junto con un DueTime expresado en unidades de 100 nanosegundos, como se muestra en la ilustración anterior. Un valor positivo para DueTime especifica una hora de expiración absoluta (desde el 1 de enero de 1601) en la que se debe llamar a la rutina CustomTimerDpc . Un valor negativo para DueTime especifica una hora de expiración relativa.

Dado que un temporizador absoluto expira en un momento específico del sistema, la duración de espera de un temporizador absoluto no se ve afectada si la hora del sistema cambia antes de que expire el temporizador. Por otro lado, un temporizador relativo siempre expira después de que transcurre el número especificado de unidades de tiempo, independientemente de los cambios en la hora absoluta del sistema.

Para invocar una rutina CustomTimerDpc repetidamente, use KeSetTimerEx para establecer el temporizador y especificar un intervalo periódico en el parámetro Period . KeSetTimerEx es igual que KeSetTimer , excepto para este parámetro adicional.

Como se muestra en la ilustración anterior, la llamada a KeSetTimer o KeSetTimerEx pone en cola el objeto de temporizador para un intervalo especificado de la siguiente manera:

  1. Cuando expira DueTime , el objeto de temporizador se desquea y se establece en el estado Signaled.

  2. Si cada procesador de la máquina está ejecutando código actualmente en un IRQL mayor o igual que DISPATCH_LEVEL, el objeto DPC asociado al objeto de temporizador se coloca en una cola DPC. De lo contrario, se llama a la rutina CustomTimerDpc .

  3. Si el objeto DPC ya estaba en la cola cuando expiró el intervalo DueTime , se llama a la rutina CustomTimerDpc tan pronto como irQL en cualquier procesador de la máquina cae por debajo de DISPATCH_LEVEL.

    Nota

    La rutina CustomTimerDpc , como todas las rutinas de DPC, se llama en IRQL = DISPATCH_LEVEL. Mientras se ejecuta una rutina DPC, se impide que todos los subprocesos se ejecuten en el mismo procesador. Los desarrolladores de controladores deben diseñar cuidadosamente sus rutinas CustomTimerDpc para que se ejecuten durante un tiempo lo más breve posible.

El intervalo de tiempo más pequeño que se puede especificar en KeSetTimer y KeSetTimerEx es de aproximadamente diez milisegundos, por lo que un controlador puede usar una rutina CustomTimerDpc cuando se sincronizan intervalos más pequeños que una rutina de IoTimer , que se ejecuta una vez por segundo, puede controlar.

Solo se puede poner en cola una instancia de un objeto de temporizador determinado en cualquier momento. Al llamar a KeSetTimer o KeSetTimerEx de nuevo con el mismo puntero de objeto Timer , se cancela el objeto de temporizador en cola y se restablece.

Configurar una rutina CustomTimerDpc es exactamente como configurar una rutina CustomDpc , con un paso adicional para inicializar el objeto de temporizador. De hecho, sus prototipos son idénticos, pero la rutina CustomTimerDpc no puede usar los dos punteros SystemArgument declarados en su prototipo.