Использование буферизованного и прямого ввода-вывода

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

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

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

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

  1. Проверьте допустимость диапазона адресов пользовательского буфера и проверка, разрешен ли соответствующий доступ на чтение или запись, используя подпрограммы поддержки ProbeForRead и ProbeForWrite. Драйвер должен заключить свои доступы к диапазону адресов буфера в обработчике исключений, предоставленном драйвером, чтобы поток пользователя не может изменить права доступа к буферу, пока драйвер обращается к памяти. Если проба вызывает исключение, драйвер должен вернуть ошибку. Драйвер должен вызывать эти подпрограммы в контексте потока, который сделал запрос ввода-вывода; Поэтому эту задачу может выполнять только драйвер более высокого уровня.

  2. Управлять буферами и операциями с памятью можно одним из следующих способов.

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

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