Поделиться через


Использование таймеров

В этом разделе описывается использование встроенной поддержки таймера платформы. Это относится как к драйверам Kernel-Mode Driver Framework (KMDF), так и к драйверам User-Mode Driver Framework (UMDF), начиная с версии 2.

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

Чтобы создать объект таймера платформы, драйвер должен вызвать метод WdfTimerCreate. Этот метод регистрирует функцию обратного вызова EvtTimerFunc и периодический временной интервал. Если вы хотите, чтобы платформа вызывала функцию обратного вызова только один раз, драйвер указывает ноль для периодического интервала времени.

Как правило, вы будете знать количество таймеров, необходимых драйверу для каждого устройства. Поэтому драйвер может создавать объекты таймера, вызывая WdfTimerCreate в функции обратного вызова EvtDriverDeviceAdd, и он может хранить дескрипторы таймеров в пространстве контекста объекта устройства или очереди .

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

Если драйвер предоставил периодический интервал времени при вызове WdfTimerCreate, таймер называется периодическим таймером. Часы периодического таймера продолжают работать после истечения начального времени ожидания, и платформа неоднократно вызывает функцию обратного вызова драйвера каждый раз, когда истекает периодический временной интервал. Периодические таймеры не запускаются автоматически. Как и не периодические таймеры, драйвер должен по-прежнему вызывать WdfTimerStart после создания таймера, чтобы запустить его в первый раз.

Драйвер может вызывать WdfTimerStart из функции обратного вызова EvtTimerFunc, чтобы перезапустить непериодический таймер после истечения срока действия.

Чтобы остановить таймер, драйвер может вызвать WdfTimerStop. Драйвер может повторно использовать таймеры, запуская и останавливая их многократно.

Когда драйвер создает объект таймера, он должен указать родительский объект. Платформа останавливает таймер и удаляет объект таймера при удалении родительского объекта. Чтобы получить родительский объект таймера, драйвер может вызвать WdfTimerGetParentObject.

В версиях KMDF до 1.9 использование объектов таймера затруднено, если необходимо, чтобы все функции обратного вызова драйвера выполнялись на уровне IRQL = PASSIVE_LEVEL. Платформа реализует функцию обратного вызова EvtTimerFunc объекта таймера в качестве отложенного вызова процедуры (DPC), который производится на уровне IRQL = DISPATCH_LEVEL. Таким образом, если требуется, чтобы код, выполняемый по истечении срока действия таймера, выполнялся на уровне PASSIVE_LEVEL, функция обратного вызова EvtTimerFunc должна поместить в очередь рабочий элемент , который выполняется на уровне PASSIVE_LEVEL.

В KMDF версии 1.9 и более поздних версиях можно создать таймер пассивного уровня, которые работают на уровне PASSIVE_LEVEL. Чтобы создать таймер пассивного уровня, укажите уровень выполнения WdfExecutionLevelPassive, когда ваш драйвер вызывает WdfTimerCreate. В результате платформа реализует функции обратного вызова EvtTimerFunc в качестве рабочих элементов, выполняемых в PASSIVE_LEVEL. Обратите внимание, что таймеры пассивного уровня не могут быть периодическими таймерами.

Начиная с версии 2.0, фреймворк UMDF реализует функции обратного вызова EvtTimerFunc объекта таймера как рабочие потоки из пула потоков пользовательского режима. В итоге функции обратного вызова таймера драйвера UMDF всегда выполняются на уровне PASSIVE_LEVEL.

Нет таймеров пробуждения

Эффективность работы системы снижается таймерами, которые неоднократно вызывают возобновление работы системы из состояний низкой мощности. Одним из способов повышения жизненного времени батареи является задержка некритических периодических операций, а не пробуждение системы. Начиная с Windows 8.1, вы можете использовать без таймеров пробуждения для выполнения таких некритических операций в драйвере KMDF или UMDF. Таймер, препятствующий пробуждению, не активирует систему, если его срок действия истекает, пока система находится в режиме энергосбережения. Вместо этого платформа вызывает функцию обратного вызова драйвера EvtTimerFunc в следующий раз, когда система полностью включена в состояние S0.

Таймеры пробуждения недоступны начиная с KMDF версии 1.13 и UMDF версии 2.0.

Чтобы создать таймер без пробуждения системы, задайте для члена TolerableDelay из WDF_TIMER_CONFIG значение TolerableDelayUnlimited.

Дополнительные сведения о таймерах без пробуждения см. в No-Wake Таймеры.

Таймеры высокого разрешения

Стандартные таймеры платформы имеют точность, которая соответствует интервалу тика системных часов, что по умолчанию составляет 15,6 миллисекунда. Начиная с Windows 8.1, можно создавать таймеров высокого разрешения. Таймер высокого разрешения имеет точность одного миллисекунда. Вы можете использовать таймер высокого разрешения для критической операции, требующей точного прогнозируемого срока действия. В результате частого обслуживания, которое требуется, таймер с высоким разрешением может привести к снижению времени работы батареи.

Таймеры высокого разрешения доступны только драйверам KMDF, начиная с KMDF версии 1.13.

Чтобы создать таймер с высоким разрешением, задайте UseHighResolutionTimer поле WDF_TIMER_CONFIG в WdfTrue, а затем настройте значение Period до нужного разрешения.

В следующей таблице показаны примеры поведения таймера на основе различных значений, которые драйвер предоставляет для Период. В этих примерах предполагается, что интервал тика системных часов составляет 15 миллисекунда.

Период, в мс Стандартный таймер Таймер высокого разрешения

10

Таймер истекает в диапазоне от 0 миллисекунд до 25 миллисекунд.

Таймер истекает как можно скорее после 10 миллисекунда.

16

Срок действия таймера истекает в диапазоне от 15 миллисекунд до 30 миллисекунд.

Таймер истекает как можно скорее после 16 миллисекунда.

Дополнительные сведения о таймерах высокого разрешения см. в High-Resolution Таймеры.

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