Выполнение запросов ввода-вывода

Каждый драйвер на основе платформы должен в конечном итоге выполнить каждый запрос ввода-вывода, получаемый от платформы. Драйверы выполняют запросы, вызывая методЫ WdfRequestComplete, WdfRequestCompleteWithInformation или WdfRequestCompleteWithPriorityBoost .

Когда следует выполнять запрос

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

  • Запрошенная операция ввода-вывода успешно завершена.

  • Запрошенная операция ввода-вывода была запущена, но завершилась сбоем.

  • Запрошенная операция ввода-вывода не поддерживается или недействительна на момент ее получения и не может быть запущена.

  • Запрошенная операция ввода-вывода была отменена.

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

Если драйвер получает неподдерживаемый или иным образом недопустимый запрос, он обычно вызывает WdfRequestComplete из обработчика запросов , который получил запрос.

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

Если драйвер перенаправит запрос ввода-вывода в целевой объект ввода-вывода, драйвер завершает запрос после того, как целевой объект ввода-вывода завершит запрос следующим образом:

  • Если драйвер синхронно пересылает запрос ввода-вывода в целевой объект ввода-вывода, вызов драйвера к целевому объекту ввода-вывода возвращается только после того, как драйвер более низкого уровня завершит запрос (если не произошла ошибка). После возврата целевого объекта ввода-вывода драйвер должен вызвать WdfRequestComplete.

  • Если ваш драйвер пересылает запрос ввода-вывода асинхронно, необходимо, чтобы драйвер был уведомлен о завершении запроса драйвером более низкого уровня. Если драйвер регистрирует функцию обратного вызова CompletionRoutine , платформа вызывает эту функцию обратного вызова после того, как целевой объект ввода-вывода завершит запрос. Функция обратного вызова CompletionRoutine обычно вызывает WdfRequestComplete.

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

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

Драйвер не завершает созданный им запрос ввода-вывода путем вызова WdfRequestCreate или WdfRequestCreateFromIrp. Вместо этого драйвер должен вызвать WdfObjectDelete , чтобы удалить объект запроса, как правило, после завершения запроса целевым объектом ввода-вывода.

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

  • Вызов WdfRequestCreate для создания одного дополнительного объекта запроса, представляющего запрос меньшего размера.

    Драйвер может отправить этот запрос синхронно в целевой объект ввода-вывода. Функция обратного вызова CompletionRoutine запроса меньшего размера может вызвать WdfRequestReuse , чтобы драйвер смог повторно использовать запрос и отправить его в целевой объект ввода-вывода. После того как целевой объект ввода-вывода завершит последний из небольших запросов, функция обратного вызова CompletionRoutine может вызвать WdfObjectDelete , чтобы удалить созданный драйвером объект запроса, а драйвер может вызвать WdfRequestComplete для завершения исходного запроса.

  • Вызов WdfRequestCreate для создания нескольких дополнительных объектов запросов, представляющих запросы меньшего размера.

    Целевые объекты ввода-вывода драйвера могут асинхронно обрабатывать эти несколько небольших запросов. Драйвер может зарегистрировать функцию обратного вызова CompletionRoutine для каждого меньшего запроса. При каждом вызове функции обратного вызова CompletionRoutine она может вызывать WdfObjectDelete , чтобы удалить созданный драйвером объект запроса. После того как целевой объект ввода-вывода завершит все небольшие запросы, драйвер может вызвать WdfRequestComplete для выполнения исходного запроса.

Предоставление сведений о завершении

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

Получение сведений о завершении

Чтобы получить сведения о запросе ввода-вывода, выполненном другим драйвером, драйвер может:

  • Вызовите WdfRequestGetStatus , чтобы получить значение состояния завершения, указанное драйвером нижнего уровня при вызове WdfRequestComplete.

  • Вызовите WdfRequestGetCompletionParams , чтобы получить структуру WDF_REQUEST_COMPLETION_PARAMS , содержащую дополнительные сведения о выполненном запросе, например дескрипторы для объектов памяти, представляющих буферы запроса, или сведения, относящиеся к шине.

    Драйвер может вызывать WdfRequestGetCompletionParams только после вызова WdfRequestSend для синхронной или асинхронной отправки запроса ввода-вывода в целевой объект ввода-вывода. Драйвер не должен вызывать WdfRequestGetCompletionParams после вызова одного из методов, которые отправляют запросы ввода-вывода целевым объектам ввода-вывода только синхронно (например , WdfIoTargetSendReadSynchronously).

  • Вызовите WdfRequestGetInformation , чтобы получить дополнительные сведения о завершении ввода-вывода, указанные драйвером нижнего уровня при вызове WdfRequestSetInformation или WdfRequestCompleteWithInformation, если драйверы в стеке драйверов предоставляют такие сведения.

Если драйвер отправляет запрос ввода-вывода синхронно, он обычно вызывает WdfRequestGetStatus, WdfRequestGetCompletionParams и WdfRequestGetInformation после возврата синхронного вызова. Если драйвер отправляет запрос ввода-вывода асинхронно, он обычно вызывает эти методы из функции обратного вызова CompletionRoutine .

Дополнительные сведения о выполнении запросов ввода-вывода см. в разделе Синхронизация кода отмены и завершения.