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


Пример запроса ввода-вывода — сведения

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

На следующем рисунке более подробно показано, как драйверы на рисунке Открытие объекта файла используют подпрограммы поддержки ввода-вывода (процедуры IoXxx ) для обработки IRP для запроса на чтение или запись.

схема, иллюстрирующая обработку irps в многоуровневых драйверах.

  1. Диспетчер ввода-вывода вызывает драйвер файловой системы (FSD) с IRP, выделенным для запроса на чтение и запись подсистемы. FSD обращается к расположению стека ввода-вывода в IRP, чтобы определить, какую операцию он должен выполнить.

  2. FSD может разбить исходный запрос на запросы меньшего размера (возможно, для нескольких драйверов устройства), вызвав подпрограмму поддержки ввода-вывода (IoAllocateIrp) один или несколько раз для выделения дополнительных irP. Дополнительные irP возвращаются в FSD с нулевым заполненным расположением стека ввода-вывода для драйверов нижнего уровня. По своему усмотрению FSD может повторно использовать исходный IRP, а не выделять дополнительные IRP, как показано на предыдущем рисунке, путем настройки расположения стека ввода-вывода следующего ниже драйвера в исходном IRP и передачи его более низким драйверам.

  3. Для каждого выделенного драйвером IRP FSD на предыдущем рисунке вызывает подпрограмму поддержки ввода-вывода для регистрации процедуры завершения, предоставляемой FSD; В процедуре завершения FSD может определить, удовлетворяют ли более низкие драйверы запросу, и может освободить каждый выделенный драйвером IRP, когда более низкие драйверы выполнили его. Диспетчер операций ввода-вывода вызовет подпрограмму завершения, предоставляемую FSD, независимо от того, успешно ли выполнено каждое выделенное драйвером IRP, выполнено с состоянием ошибки или отменено. Драйвер более высокого уровня отвечает за освобождение всех IRP, которые он выделяет и настраивает от своего имени для драйверов более низкого уровня. Диспетчер операций ввода-вывода освобождает выделенные им irP после их завершения всеми драйверами.

    Затем FSD вызывает подпрограмму поддержки ввода-вывода (IoGetNextIrpStackLocation) для доступа к расположению стека ввода-вывода драйвера следующего уровня, чтобы настроить запрос на следующий драйвер ниже. (На предыдущем рисунке следующим драйвером ниже является драйвер самого низкого уровня.) Затем FSD вызывает подпрограмму поддержки ввода-вывода (IoCallDriver), чтобы передать этот IRP в следующий драйвер ниже.

  4. При вызове с помощью IRP драйвер самого низкого уровня проверяет расположение стека ввода-вывода, чтобы определить, какую операцию (указанную кодом функции IRP_MJ_XXX ) он должен выполнять на целевом устройстве. Целевое устройство представлено объектом устройства в указанном расположении стека ввода-вывода и передается вместе с IRP драйверу. Драйвер самого низкого уровня может предположить, что диспетчер операций ввода-вывода перенаправил IRP в точку входа, определенную драйвером для операции IRP_MJ_XXX (здесь IRP_MJ_READ или IRP_MJ_WRITE), а драйвер более высокого уровня проверил допустимость других параметров для запроса.

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

  5. Диспетчер ввода-вывода определяет, занят ли драйвер обработкой другого IRP для целевого устройства, помещает его в очередь, если он есть, и возвращает его. В противном случае диспетчер ввода-вывода направляет IRP в подпрограмму, предоставляемую драйвером, которая запускает операцию ввода-вывода на своем устройстве. (На этом этапе оба драйвера на предыдущем рисунке и диспетчер ввода-вывода возвращают управление.)

  6. Когда устройство прерывает работу, подпрограмма обслуживания прерываний (ISR) драйвера выполняет только столько же работы, сколько необходимо для остановки прерывания устройства и сохранения необходимого контекста об операции. Затем ISR вызывает подпрограмму поддержки ввода-вывода (IoRequestDpc) с IRP для постановки в очередь подпрограммы DPC (отложенный вызов процедур) для выполнения запрошенной операции с более низким приоритетом оборудования, чем ISR.

  7. Когда DPC драйвера получает управление, он использует контекст (переданный в вызове ISR IoRequestDpc) для завершения операции ввода-вывода. DPC вызывает подпрограмму поддержки для вывода в очередь следующего IRP (если таковой имеется) и передачи этого IRP в подпрограмму, предоставляемую драйвером, которая запускает операции ввода-вывода на устройстве (см. шаг 5). Затем DPC задает состояние только что завершенной операции в блоке состояния ввода-вывода IRP и возвращает его диспетчеру ввода-вывода с помощью IoCompleteRequest.

  8. Диспетчер ввода-вывода обнуляет расположение стека ввода-вывода драйвера самого низкого уровня в IRP и вызывает зарегистрированную процедуру завершения файловой системы (см. шаг 3) с выделенным FSD IRP. Эта подпрограмма завершения проверяет блок состояния ввода-вывода, чтобы определить, следует ли повторить запрос или обновить внутреннее состояние исходного запроса, и освободить выделенный драйвером IRP. Файловая система может собирать сведения о состоянии для всех выделенных драйверами IRP, отправляемых в драйверы более низкого уровня, чтобы задать состояние ввода-вывода и завершить исходное IRP. Когда файловая система завершит исходное IRP, диспетчер ввода-вывода возвращает значение и NTSTATUS исходному инициатору запроса (собственная функция подсистемы) операции ввода-вывода.

Как и драйвер файловой системы, показанный на рисунке Обработка IRP на рисунке Многоуровневые драйверы , любой новый драйвер, добавленный в цепочку существующих драйверов, может выполнять все следующие действия:

  • Задайте собственную подпрограмму завершения в IRP. Подпрограмма IoCompletion проверяет блок состояния ввода-вывода, чтобы определить, завершили ли более низкие драйверы IRP успешно, отменили его и (или) завершили его с ошибкой. Подпрограмма завершения также может обновить любое состояние IRP, сохраненное драйвером, освободить все ресурсы, связанные с операцией, выделенные драйвером, и т. д. перед завершением IRP. Кроме того, подпрограмма завершения может отложить завершение IRP (информируя диспетчера ввода-вывода о том, что требуется дополнительная обработка ВП), и может отправить еще один запрос драйверу следующего более низкого уровня, прежде чем разрешить выполнение IRP.

  • Настройте расположение стека ввода-вывода следующего драйвера нижнего уровня в выделенных им irPs и отправьте запросы драйверу следующего нижнего уровня.

  • Передайте все входящие запросы в более низкие драйверы, настроив расположение стека ввода-вывода следующего ниже драйвера в каждом IRP и вызвав IoCallDriver. (Обратите внимание, что для irP с основным кодом функции IRP_MJ_POWER драйверы должны использовать PoCallDriver.)

Каждый созданный драйвером объект устройства представляет физическое, логическое или виртуальное устройство, для которого конкретный драйвер выполняет запросы ввода-вывода. Подробные сведения о создании и настройке объекта устройства см. в разделе Объекты устройства и стеки устройств.

Как также показано на рисунке Обработка IRP в многоуровневых драйверах , большинство драйверов обрабатывают каждый IRP поэтапно с помощью набора системных стандартных процедур, определенных драйвером, но драйверы на разных уровнях в цепочке обязательно имеют разные стандартные подпрограммы. Например, только драйверы самого низкого уровня обрабатывают прерывания с физического устройства, поэтому только драйвер самого низкого уровня будет иметь ISR и DPC, которые выполняют операции ввода-вывода, управляемые прерыванием. С другой стороны, поскольку такой драйвер знает, что операции ввода-вывода завершены при получении прерывания от устройства, ему не требуется процедура завершения. Только драйвер более высокого уровня будет иметь одну или несколько процедур завершения, таких как FSD на этом рисунке.