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


Настройка и использование очередей устройств

Драйвер настраивает объект очереди устройства, вызывая KeInitializeDeviceQueue при инициализации драйвера или устройства. После запуска устройств драйвер вставляет IRP в эту очередь, вызывая KeInsertDeviceQueue или KeInsertByKeyDeviceQueue. На следующем рисунке показаны эти вызовы.

настройка и использование очередей устройств.

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

Если драйвер предоставляет хранилище для объекта очереди устройства в расширении устройства, он вызывает KeInitializeDeviceQueue после создания объекта устройства и перед запуском устройства. Другими словами, драйвер может инициализировать очередь из своей процедуры AddDevice или при обработке запроса IRP_MN_START_DEVICE PnP. При вызове KeInitializeDeviceQueue драйвер передает указатель на хранилище, которое он предоставляет для объекта очереди устройства.

После запуска устройств драйвер может вставить IRP в очередь устройств, вызвав KeInsertDeviceQueue, которая помещает IRP в хвост очереди, или KeInsertByKeyDeviceQueue, который помещает IRP в очередь в соответствии со значением SortKey , определяемым драйвером, как показано на предыдущем рисунке.

Каждая из этих подпрограмм поддержки возвращает логическое значение, указывающее, вставлена ли IRP в очередь. Каждый из этих вызовов также устанавливает состояние объекта очереди устройства в состояние Занято, если очередь в данный момент пуста (не занята). Однако если очередь пуста (не занята), ни подпрограмма KeInsertXxxDeviceQueue не вставляет IRP в очередь. Вместо этого он устанавливает состояние объекта очереди устройства в значение Busy и возвращает значение FALSE. Так как IRP не поставлен в очередь, драйвер должен передать его в другую подпрограмму драйвера для дальнейшей обработки.

При настройке дополнительных очередей устройств следуйте этим рекомендациям по реализации:

Когда вызов KeInsertXxxDeviceQueue возвращает значение FALSE, вызывающий объект должен передать IRP, на который он пытался ставиться в очередь для дальнейшей обработки, в другую подпрограмму драйвера. Однако вызов KeInsertXxxDeviceQueue изменяет состояние объекта очереди устройства на Занят, поэтому следующий IRP вставляется в очередь, если драйвер не вызывает KeRemoveXxxDeviceQueue первым.

Если для объекта очереди устройства задано состояние Занято, драйвер может вывести IRP из очереди для дальнейшей обработки или сбросить состояние до Not-Busy, вызвав одну из следующих процедур поддержки:

  • KeRemoveDeviceQueue для удаления IRP в начале очереди

  • KeRemoveByKeyDeviceQueue для удаления IRP, выбранного в соответствии со значением SortKey , определенным драйвером

  • KeRemoveEntryDeviceЗапрос для удаления определенного IRP в очереди или определения того, находится ли конкретный IRP в очереди

    KeRemoveEntryDeviceQueue возвращает логическое значение, указывающее, находилась ли IRP в очереди устройств.

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

Каждый объект очереди устройства защищен встроенной исполнительной спин-блокировкой (не показано на рисунке Использование объекта очереди устройства ). В результате драйвер может вставить IRP в очередь и удалить их в многопроцессорном режиме из любой подпрограммы драйвера, работающей в режиме меньше или равно IRQL = DISPATCH_LEVEL. Из-за этого ограничения IRQL драйвер не может вызывать подпрограмму KeXxxDeviceQueue из своих процедур ISR или SynchCritSection , которые выполняются в DIRQL.

Дополнительные сведения см. в разделе Управление приоритетами оборудования и спин-блокировками . Требования IRQL для конкретной процедуры поддержки см. на странице справочника по подпрограмме.