Общие сведения об объектах диспетчера ядра
Ядро определяет набор типов объектов, называемых объектами диспетчера ядра или просто объектами диспетчера. К объектам диспетчера относятся объекты таймера, объекты событий, объекты семафора, объекты мьютекса и объекты потоков.
Драйверы могут использовать объекты диспетчера в качестве механизмов синхронизации в контексте неарбитарного потока при выполнении в IRQL, равном PASSIVE_LEVEL.
Состояния объектов диспетчера
Каждый тип объекта диспетчера, определенный ядром, имеет состояние , которое имеет значение Signaled или Not-Signaled.
Группа потоков может синхронизировать свои операции, если один или несколько потоков вызывают KeWaitForSingleObject, KeWaitForMutexObject или KeWaitForMultipleObjects. Эти функции принимают указатели объектов диспетчера в качестве входных данных и ожидают, пока другая подпрограмма или поток не установит для одного или нескольких объектов диспетчера состояние Signaled.
Когда поток вызывает KeWaitForSingleObject для ожидания объекта диспетчера (или KeWaitForMutexObject для мьютекса), поток переводится в состояние ожидания , пока объект диспетчера не перейдет в состояние Signaled. Поток может вызывать KeWaitForMultipleObjects , чтобы дождаться, пока любой из наборов объектов диспетчера будет установлен в значение Signaled или для всех.
Всякий раз, когда объекту диспетчера присваивается состояние Signaled, ядро изменяет состояние любого потока, ожидающего готовности этого объекта. (Таймеры синхронизации и события синхронизации являются исключениями из этого правила. При сигнале события синхронизации или таймера только один ожидающий поток устанавливается в состояние готовности. Дополнительные сведения см. в разделе Объекты таймера и DPC и объекты событий.) Поток в состоянии готовности будет запланирован на выполнение в соответствии с текущим приоритетом потока во время выполнения и текущей доступностью процессоров для любого потока с этим приоритетом.
Когда водители могут ждать объектов диспетчера?
Как правило, водители могут ждать установки объектов диспетчера, только если выполняется хотя бы одно из следующих обстоятельств:
Драйвер выполняется в контексте неarbitrary потока.
То есть можно определить поток, который перейдет в состояние ожидания. На практике единственными подпрограммами драйвера, которые выполняются в контексте неarbitrary потока, являются подпрограммы DriverEntry, AddDevice, Reinitialize и Unload любого драйвера, а также подпрограммы диспетчеризации драйверов самого высокого уровня. Все эти подпрограммы вызываются непосредственно системой.
Драйвер выполняет полностью синхронный запрос ввода-вывода.
То есть ни один драйвер не помещает в очередь какие-либо операции при обработке запроса ввода-вывода, и ни один драйвер не возвращается до тех пор, пока приведенный ниже драйвер не завершит обработку запроса.
Кроме того, драйвер не может войти в состояние ожидания, если он выполняется в или выше IRQL, равном DISPATCH_LEVEL.
В зависимости от этих ограничений необходимо использовать следующие правила:
Подпрограммы DriverEntry, AddDevice, Reinitialize и Unload любого драйвера могут ждать объектов диспетчера.
Подпрограммы диспетчеризации драйвера самого высокого уровня могут ждать объектов диспетчера.
Подпрограммы диспетчеризации драйверов более низкого уровня могут ждать объектов диспетчеризации, если операция ввода-вывода синхронна, например операции создания, очистки, завершения работы и закрытия, некоторые операции управления вводом-выводом устройства, а также некоторые операции PnP и питания.
Подпрограммы диспетчеризации драйверов более низкого уровня не могут ждать завершения асинхронных операций ввода-вывода в объекте диспетчера.
Подпрограмма драйвера, которая выполняется на DISPATCH_LEVEL IRQL или выше, не должна ждать, пока объект диспетчера будет установлен в состояние Signaled .
Драйвер не должен пытаться дождаться, пока объект диспетчера будет установлен в состояние Signaled для завершения операции передачи на устройство подкачки или с устройства подкачки.
Процедуры диспетчеризации драйвера, обслуживающие запросы на чтение и запись, обычно не могут ждать, пока объект диспетчера будет установлен в состояние Signaled .
Подпрограмма диспетчеризации для запроса управления вводом-выводом устройства может ожидать, пока объект диспетчера будет установлен в состояние Signaled , только если тип передачи для кода управления вводом-выводом METHOD_BUFFERED.
Драйверы SCSI miniport не должны использовать объекты диспетчера ядра. Драйверы SCSI miniport должны вызывать только подпрограммы библиотеки портов SCSI.
Все остальные стандартные подпрограммы драйвера выполняются в произвольном контексте потока: в любом потоке, который является текущим, когда подпрограмма драйвера вызывается для обработки операции в очереди или для обработки прерывания устройства. Кроме того, большинство стандартных подпрограмм драйвера выполняются на вызове IRQL в DISPATCH_LEVEL или для драйверов устройств в DIRQL.
При необходимости драйвер может создать выделенный для устройства поток, который может ждать других процедур драйвера (за исключением процедуры ISR или SynchCritSection ), чтобы установить объект диспетчера в состояние Signaled и вернуться к состоянию Not-Signaled.
В целом, если предполагается, что новый драйвер устройства часто будет зависать на более чем 50 микросекунд, ожидая изменения состояния устройства во время операций ввода-вывода, рассмотрите возможность реализации драйвера с выделенным для устройства потоком. Если драйвер устройства также является драйвером самого высокого уровня, рассмотрите возможность использования системных рабочих потоков и реализации одной или нескольких процедур обратного вызова рабочего потока. См . статьи PsCreateSystemThread и Управление заблокированными очередями с помощью потока Driver-Created.