Использование таймеров
В этом разделе описывается, как использовать встроенную поддержку таймера платформы. Он применяется как к драйверам 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. Обратите внимание, что таймеры пассивного уровня не могут быть периодическими.
Начиная с версии UMDF 2.0, платформа реализует функции обратного вызова EvtTimerFunc объекта таймера в качестве рабочих потоков из пула потоков пользовательского режима. В результате функции обратного вызова таймера драйвера UMDF всегда выполняются в PASSIVE_LEVEL.
Нет таймеров пробуждения
Эффективность энергопотребления системы снижается за счет таймеров, которые неоднократно приводят к возобновлению работы системы из состояний с низким энергопотреблением. Одним из способов повышения времени работы батареи является задержка некритических периодических операций, а не пробуждение системы. Начиная с Windows 8.1, вы не можете использовать таймеры пробуждения для выполнения таких некритических операций в драйвере KMDF или UMDF. Таймер без пробуждения не пробуждает систему, если срок ее действия истекает, пока система находится в состоянии с низким энергопотреблением. Вместо этого платформа вызывает функцию обратного вызова EvtTimerFunc драйвера при следующем включении системы в состоянии S0.
Таймеры пробуждения недоступны, начиная с KMDF версии 1.13 и UMDF версии 2.0.
Чтобы создать таймер без пробуждения, задайте для элемента TolerableDelayэлемента WDF_TIMER_CONFIG значение TolerableDelayUnlimited.
Дополнительные сведения об отсутствии таймеров пробуждения см. в разделе Таймеры без пробуждения.
Таймеры высокого разрешения
Таймеры стандартной платформы имеют точность, соответствующую интервалу тактов системных часов, который по умолчанию составляет 15,6 миллисекунда. Начиная с Windows 8.1, можно создавать таймеры с высоким разрешением. Таймер с высоким разрешением имеет точность в 1 миллисекунда. Вы можете использовать таймер с высоким разрешением для критической операции, требующей точного и предсказуемого срока действия. В результате частого обслуживания, которое требуется, таймер с высоким разрешением может привести к уменьшению времени работы батареи.
Таймеры высокого разрешения доступны только для драйверов KMDF, начиная с KMDF версии 1.13.
Чтобы создать таймер с высоким разрешением, задайте для элемента UseHighResolutionTimerэлемента WDF_TIMER_CONFIGзначение WdfTrue, а затем настройте для параметра Period требуемое разрешение.
В следующей таблице приведены примеры поведения таймера на основе различных значений, которые драйвер предоставляет для параметра Period. В этих примерах предполагается, что интервал тактов системных часов составляет 15 миллисекундах.
Точка, в мс | Стандартный таймер | Таймер высокого разрешения |
---|---|---|
10 |
Срок действия таймера истекает от 0 до 25 миллисекунд. |
Срок действия таймера истекает через 10 миллисекунда. |
16 |
Срок действия таймера истекает от 15 до 30 миллисекунд. |
Срок действия таймера истекает через 16 миллисекунда. |
Дополнительные сведения о таймерах с высоким разрешением см. в разделе Таймеры высокого разрешения.
Дополнительные сведения о том, как точность таймера связана с степенью детализации системных часов, см. в разделе Точность таймера.