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


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

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

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

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

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

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

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

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

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