Регистрация и постановка в очередь подпрограммы CustomTimerDpc

Драйвер может зарегистрировать подпрограмму CustomTimerDpc , вызвав следующие подпрограммы, обычно из ее процедуры AddDevice :

  1. KeInitializeDpc для регистрации своей подпрограммы

  2. KeInitializeTimer или KeInitializeTimerEx для настройки объекта таймера

Впоследствии драйвер может вызвать KeSetTimer или KeSetTimerEx , чтобы указать время окончания срока действия и добавить объект таймера в очередь таймера системы. По истечении срока действия система выводит объект таймера из очереди и вызывает подпрограмму CustomTimerDpc . На следующем рисунке показаны эти вызовы.

схема, иллюстрирующая использование объектов таймера и dpc для подпрограммы customtimerdpc.

Как показано на предыдущем рисунке, драйвер должен предоставить хранилище как для объекта DPC, так и для объекта таймера. Большинство драйверов предоставляют хранилище для этих объектов в расширении устройства или в другой выделенной драйвером резидентной памяти.

При вызове KeSetTimer драйвер передает указатели на объекты Dpc и Timer , а также DueTime , выраженный в единицах 100 наносекунд, как показано на предыдущем рисунке. Положительное значение для DueTime указывает абсолютное время окончания срока действия (с 1 января 1601 г.), в которое должна вызываться подпрограмма CustomTimerDpc . Отрицательное значение для DueTime указывает относительное время окончания срока действия.

Так как абсолютный таймер истекает в определенное системное время, длительность ожидания абсолютного таймера не влияет на изменение системного времени до истечения срока действия таймера. С другой стороны, относительный таймер всегда истекает по истечении указанного количества единиц времени, независимо от изменений в абсолютном системном времени.

Чтобы повторно вызвать подпрограмму CustomTimerDpc , используйте KeSetTimerEx , чтобы задать таймер и указать повторяющийся интервал в параметре Period . KeSetTimerEx аналогично KeSetTimer , за исключением этого дополнительного параметра.

Как показано на предыдущем рисунке, вызов KeSetTimer или KeSetTimerEx помещает объект таймера в очередь на указанный интервал следующим образом:

  1. По истечении срока действия DueTime объект таймера выдается из очереди и устанавливается в состояние Signaled .

  2. Если каждый процессор на компьютере в настоящее время выполняет код в IRQL больше или равен DISPATCH_LEVEL, объект DPC, связанный с объектом таймера, помещается в очередь DPC. В противном случае вызывается подпрограмма CustomTimerDpc .

  3. Если объект DPC уже находился в очереди по истечении срока действия интервала DueTime , подпрограмма CustomTimerDpc вызывается сразу после того, как значение IRQL на любом процессоре на компьютере опускается ниже DISPATCH_LEVEL.

    Примечание

    Подпрограмма CustomTimerDpc, как и все подпрограммы DPC, вызывается в IRQL = DISPATCH_LEVEL. Во время выполнения подпрограммы DPC все потоки не могут выполняться на одном процессоре. Разработчикам драйверов следует тщательно разработать подпрограммы CustomTimerDpc , чтобы они работали в течение как можно более короткого времени.

Минимальный интервал времени, который можно указать для KeSetTimer и KeSetTimerEx , составляет около десяти миллисекунд, поэтому драйвер может использовать подпрограмму CustomTimerDpc , если интервалы времени меньше, чем может обрабатывать подпрограмма IoTimer , которая выполняется один раз в секунду.

В любой момент можно поместить в очередь только один экземпляр определенного объекта таймера. При повторном вызове KeSetTimer или KeSetTimerEx с тем же указателем на объект Таймер отменяет объект таймера в очереди и сбрасывает его.

Настройка подпрограммы CustomTimerDpc похожа на настройку подпрограммы CustomDpc с дополнительным шагом для инициализации объекта таймера. На самом деле их прототипы идентичны, но подпрограмма CustomTimerDpc не может использовать два указателя SystemArgument , объявленные в прототипе.