Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
На следующем рисунке показано использование таймера уведомлений для настройки интервала времени ожидания для операции, а затем ожидания, пока другие подпрограммы драйверов обрабатывают запрос ввода-вывода.
Как показано на предыдущем рисунке, драйвер должен предоставить хранилище для объекта таймера, который должен быть инициализирован вызовом KeInitializeTimer с указателем на это хранилище. Драйвер обычно вызывает этот вызов из своей подпрограммы AddDevice .
В контексте конкретного потока, например созданного драйвером потока или потока, запрашивающего синхронную операцию ввода-вывода, драйвер может ждать своего объекта таймера, как показано на предыдущем рисунке:
Поток вызывает KeSetTimer с указателем на объект таймера и заданное значение DueTime , выраженное в единицах 100 наносекунд. Положительное значение для DueTime указывает абсолютное время, в течение которого объект таймера должен быть удален из очереди таймера ядра и задано состояние Signaled. Отрицательное значение для DueTime указывает интервал относительно текущего системного времени.
Обратите внимание, что поток (или подпрограмма драйвера, выполняемая в системном потоке) передает нулевой указатель для объекта DPC (как показано ранее на рисунке, иллюстрирующем использование таймера и объектов DPC для подпрограммы CustomTimerDpc) при вызове KeSetTimer, если он ожидает объект таймера, а не ставит в очередь подпрограмму CustomTimerDpc.
Поток вызывает KeWaitForSingleObject с указателем на объект таймера, который переводит поток в режим ожидания, пока объект таймера находится в очереди таймеров, управляемой ядром.
Срок действия заданного DueTime истекает.
Ядро извлекает объект таймера из очереди, устанавливает его в сигнализируемое состояние и изменяет состояние потока от состояния ожидания к состоянию готовности.
Ядро отправляет поток для выполнения сразу после того, как процессор доступен: т. е. ни один другой поток с более высоким приоритетом в настоящее время находится в состоянии готовности, и подпрограммы режима ядра не выполняются на более высоком уровне IRQL.
Подпрограммы драйверов, выполняемые на IRQL >= DISPATCH_LEVEL, могут прерывать запросы по истечении времени ожидания, используя объект таймера с соответствующим объектом DPC для постановки в очередь подпрограммы CustomTimerDpc, предоставленной драйвером. Только подпрограммы драйверов, выполняемые в контексте непарбитрарного потока, могут ожидать ненулевого интервала в объекте таймера, как показано на предыдущем рисунке.
Как и каждый другой поток, созданный драйвером, он представлен объектом потока ядра, который также является объектом диспетчера. Следовательно, драйверу не нужно, чтобы созданный драйвером поток использовал объект таймера, чтобы добровольно поместить себя в состояние ожидания для заданного интервала. Вместо этого поток может вызывать KeDelayExecutionThread с заданным вызывающим интервалом. Дополнительные сведения об этом методе см. в разделе "Опрос устройства".
DriverEntry, Повторно инициализировать и выгрузить подпрограммы также выполняются в контексте системного потока, поэтому драйверы могут вызывать KeWaitForSingleObject с объектом таймера с инициализацией драйвера или KeDelayExecutionThread во время инициализации или выгрузки. Драйвер устройства может вызывать KeStallExecutionProcessor для очень короткого интервала (предпочтительно менее 50 микросекунд), если устройство должно ожидать обновления состояния во время инициализации.
Однако драйверы более высокого уровня обычно используют другой механизм синхронизации в своих подпрограммах DriverEntry и Повторно инициализировать вместо использования объекта таймера. Драйверы более высокого уровня всегда должны разрабатываться так, чтобы накладываться на любой драйвер нижнего уровня определенного типа или типов устройств. Таким образом, драйвер более высокого уровня, как правило, замедляет загрузку, если он ожидает на объекте таймера или вызывает KeDelayExecutionThread, так как такой драйвер должен ждать достаточно долго, чтобы поддерживать самое медленное из возможных устройств, которые его поддерживают. Обратите внимание также, что "безопасный", но минимальный интервал для такого ожидания очень трудно определить.
Аналогичным образом драйверы PnP не должны ожидать выполнения других действий, но вместо этого следует использовать механизм уведомлений диспетчера PnP.