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


Управление очередями ввода-вывода

Запуск очереди ввода-вывода

Когда драйвер вызывает WdfIoQueueCreate для создания очереди ввода-вывода, платформа автоматически разрешает очереди получать запросы ввода-вывода и доставлять их драйверу.

Драйверы обычно вызывают WdfIoQueueCreate из функции обратного вызова EvtDriverDeviceAdd . Платформа может начать доставку запросов ввода-вывода драйверу после возврата функции обратного вызова EvtDriverDeviceAdd .

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

Остановка и перезапуск очереди ввода-вывода

Драйвер может вызывать WdfIoQueueStop или WdfIoQueueStopSynchronous, чтобы временно предотвратить доставку запросов ввода-вывода платформой из очереди ввода-вывода. Чтобы возобновить доставку запросов ввода-вывода, драйвер вызывает WdfIoQueueStart.

Если драйвер использует очереди ввода-вывода, управляемые питанием, платформа автоматически останавливает очереди устройства, когда устройство выходит из рабочего (D0) состояния, а платформа перезапускает очереди, когда состояние устройства вернется в D0.

Добавление запросов в очередь ввода-вывода

Когда система отправляет драйверу запрос на чтение, запись или управление вводом-выводом устройства, платформа помещает запрос в очередь ввода-вывода. Драйвер может управлять типами запросов, которые платформа хранит в каждой очереди, вызывая WdfDeviceConfigureRequestDispatching.

Драйвер также может повторно отправлять запросы, полученные от платформы, путем вызова WdfRequestForwardToIoQueue.

Получение запросов из очереди ввода-вывода

Если драйвер задает последовательный или параллельный метод диспетчеризации для очереди ввода-вывода, он получает запросы в обработчиках запросов.

Если драйвер указывает ручной или последовательный метод диспетчеризации, он может получать запросы путем вызова WdfIoQueueRetrieveNextRequest или WdfIoQueueRetrieveRequestByFileObject.

Поиск запроса ввода-вывода

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

  1. Вызовите WdfIoQueueFindRequest , чтобы найти запрос, соответствующий заданным драйвером критериям.

  2. Вызовите WdfIoQueueRetrieveFoundRequest , чтобы получить запрос, расположенный wdfIoQueueFindRequest .

Очистка или очистка очереди ввода-вывода

Очистка очереди ввода-вывода означает остановку вставки запросов ввода-вывода в очередь и отмену всех запросов, которые уже находятся в очереди.

Очистка очереди ввода-вывода означает остановку вставки запросов ввода-вывода в очередь, а также позволяет доставлять драйверу все запросы, которые уже находятся в очереди.

Как правило, драйверы очищают или сливают свои очереди только в том случае, если очереди не управляются питанием. Для очередей ввода-вывода, управляемых питанием, драйверы могут предоставлять функции обратного вызова EvtIoStop и EvtIoResume .

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

Если вы хотите, чтобы драйвер очищал или стекал очередь ввода-вывода, драйвер может вызвать один из следующих методов объекта очереди:

  • WdfIoQueuePurge или WdfIoQueuePurgeSynchronously, чтобы остановить постановку запросов ввода-вывода в очередь ввода-вывода и отменить необработанные запросы.

  • WdfIoQueueDrain или WdfIoQueueDrainSynchronously, чтобы остановить постановку в очередь запросов ввода-вывода в очередь ввода-вывода, позволяя доставлять и обрабатывать уже поставленные в очереди запросы.

Соблюдайте осторожность при вызове WdfIoQueueDrain и WdfIoQueueDrainSynchronous. Так как операция очистки ожидает завершения запросов, следует выполнять очистку очереди только в том случае, если вы уверены, что ожидающие запросы очереди будут выполнены своевременно. Если вы не знаете, сколько времени потребуется для выполнения запросов ввода-вывода и вы можете отменить невыполненные запросы, рассмотрите возможность очистки очереди.

Перемещение запросов из одной очереди ввода-вывода в другую

После получения запроса на ввод-вывод драйвером может потребоваться повторно отправить запрос в другую очередь ввода-вывода. Для этого драйвер вызывает WdfRequestForwardToIoQueue или WdfRequestForwardToParentDeviceIoQueue, который добавляет запрос к хвосту указанной очереди. В конечном итоге платформа снова доставляет запрос драйверу с помощью метода диспетчеризации указанной очереди. Дополнительные сведения о перемещении запросов ввода-вывода из одной очереди ввода-вывода в другую см. в разделе Повторная постановка в очередь запросов ввода-вывода.

Перехват запроса ввода-вывода до его постановки в очередь

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

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

Как правило, когда функция обратного вызова EvtIoInCallerContext получает запрос, она выполняет некоторую предварительную обработку запроса. Затем функция обратного вызова вызывает WdfDeviceEnqueueRequest, который возвращает запрос к платформе. Затем платформа может поместить запрос в соответствующую очередь ввода-вывода, как это было бы, если бы она не вызвала функцию обратного вызова EvtIoInCallerContext .

Основная причина, по которой драйвер может предоставить функцию обратного вызова EvtIoInCallerContext , заключается в том, что драйвер должен обрабатывать операции ввода-вывода, которые поддерживают метод ввода-вывода, который не называется ни буферным, ни прямым вводом-выводом. Для этого метода ввода-вывода драйвер должен получить доступ к полученным буферам в контексте процесса инициатора запроса ввода-вывода. Дополнительные сведения см. в статье Доступ к буферам данных в драйверах Framework-Based.

Получение свойств очереди ввода-вывода

Чтобы получить свойства объекта очереди платформы, драйвер может вызвать следующие методы: