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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  2. Вызовите WdfIoQueueRetrieveFoundRequest, чтобы получить запрос, который нашёл WdfIoQueueFindRequest.

Удаление или слив очереди ввода-вывода

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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