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


Отмена запросов ввода-вывода

Выполняющиеся операции ввода-вывода устройства (например, запрос на чтение нескольких блоков с диска) могут быть отменены приложением, системой или драйвером. Если операция ввода-вывода устройства отменена, диспетчер операций ввода-вывода пытается отменить все необработанные запросы ввода-вывода, связанные с операцией ввода-вывода. Драйверы устройства могут регистрироваться, чтобы получать уведомления, когда диспетчер ввода-вывода пытается отменить запросы ввода-вывода, и драйверы могут отменить запросы, принадлежащие им, завершить с состоянием завершения STATUS_CANCELLED.

Фреймворк обрабатывает часть работы по отмене для драйверов, основанных на фреймворке. Если операция ввода-вывода устройства отменена, платформа завершает следующие запросы ввода-вывода (с состоянием завершения STATUS_CANCELLED), связанные с отмененной операцией:

  • Незавершенные запросы ввода-вывода, которые фреймворк помещал в очередь ввода-вывода драйвера по умолчанию.

  • Незавершенные запросы ввода-вывода, которые фреймворк перенаправил в другую очередь, так как драйвер вызвал WdfDeviceConfigureRequestDispatching.

Так как платформа отменяет эти запросы, она не доставляет их драйверу.

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

Иногда драйвер получает запрос ввода-вывода из очереди ввода-вывода, но вместо обработки запроса драйвер повторно запрашивает запрос к той же или другой очереди ввода-вывода для последующей обработки. Ниже приведены примеры этой ситуации:

  • Фреймворк передает запрос ввода-вывода одному из обработчиков запросов драйвера, затем драйвер вызывает либо WdfRequestForwardToIoQueue (или WdfRequestForwardToParentDeviceIoQueue) для размещения запроса в другую очередь, либо WdfRequestRequeue, чтобы поместить запрос обратно в ту же очередь.

  • Платформа передает запрос ввода-вывода в функцию обратного вызова драйвера EvtIoInCallerContext. Драйвер затем вызывает WdfDeviceEnqueueRequest, чтобы передать запрос обратно в платформу, и платформа в дальнейшем помещает запрос в одну из очередей ввода-вывода драйвера.

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

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

Вызов WdfRequestMarkCancelable или WdfRequestMarkCancelableEx

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

Драйвер должен вызывать WdfRequestMarkCancelable или WdfRequestMarkCancelableEx, если он будет владеть запросом в течение относительно длительного времени. Например, драйверу может потребоваться ждать ответа от устройства или ожидать, пока более низкие драйверы завершат выполнение набора запросов, которые были созданы драйвером при получении одного запроса.

Если драйвер не вызывает WdfRequestMarkCancelable или WdfRequestMarkCancelableExили если драйвер вызывает WdfRequestUnmarkCancelable после вызова WdfRequestMarkCancelable или WdfRequestMarkCancelableEx, драйвер не знает об отмене и поэтому обрабатывает запрос как обычно.

Вызов WdfRequestIsCanceled

Если драйвер не вызвал WdfRequestMarkCancelable или WdfRequestMarkCancelableEx для регистрации функции обратного вызова EvtRequestCancel, он может вызвать WdfRequestIsCanceled, чтобы определить, пытался ли менеджер ввода-вывода отменить запрос ввода-вывода. Если WdfRequestIsCanceled возвращает TRUE и драйвер владеет запросом, драйвер должен отменить запрос. Если драйвер не владеет запросом, он не должен вызывать WdfRequestIsCanceled.

Драйвер, который не вызывал WdfRequestMarkCancelable или WdfRequestMarkCancelableEx может вызывать WdfRequestIsCanceled в следующих обстоятельствах:

  • Драйвер, ожидающий прерываний устройства, может вызывать WdfRequestIsCanceled из функции обратного вызова EvtInterruptDpc.

  • Драйвер, который выполняет опрос своего устройства, может вызвать WdfRequestIsCanceled из потока опроса.

  • Драйвер, который разбивает транзакцию DMA на несколько небольших передач, может вызывать WdfRequestIsCanceled после завершения каждой передачи.

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

Отмена запроса

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

  • Остановка выполняющейся операции ввода-вывода.

  • Не перенаправляя запрос на целевой объект ввода-вывода.

  • Вызов WdfRequestCancelSentRequest для попытки отменить запрос, который драйвер ранее отправил в целевой объект ввода/вывода.

Если драйвер отменяет запрос ввода-вывода для объекта запроса, полученного драйвером из фреймворка, драйвер должен всегда выполнять запрос, вызывая WdfRequestComplete, WdfRequestCompleteWithInformationили WdfRequestCompleteWithPriorityBoostс параметром состояния STATUS_CANCELLED. (Если драйвер вызвал WdfRequestCreate для создания объекта запроса, то драйвер вызывает WdfObjectDelete вместо завершения запроса.)

Синхронизация процесса отмены

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