Читаем 3.Внутреннее устройство Windows (гл. 8-11) полностью

• Прямой ввод-вывод (direct I/O) Создавая IRP, диспетчер ввода-вывода блокирует пользовательский буфер в памяти (делает его неподкачиваемым). Закончив работу с IRP, диспетчер ввода-вывода разблокирует буфер. Диспетчер хранит описание этой памяти в форме MDL (memory descriptor list). MDL указывает объем физической памяти, занятой буфером (подробнее о MDL см. Windows DDK). Устройствам, использующим DMA (прямой доступ к памяти), требуется лишь физическое описание буфера, поэтому таким устройствам достаточно MDL. (Устройства, поддерживающие DMA, передают данные в память компьютера напрямую, не используя процессор.) Ho, если драйверу нужен доступ к содержимому буфера, он может спроецировать его на системное адресное пространство.

• Ввод-вывод без управления (neither I/O) Диспетчер ввода-вывода не участвует в управлении буферами. Ответственность за управление ими возлагается на драйвер устройства.

При любом типе управления буферами диспетчер ввода-вывода помещает в IRP ссылки на буферы ввода и вывода. Тип управления буферами, реализуемого диспетчером ввода-вывода, зависит от типа управления, запрошенного драйвером для операций конкретного типа. Драйвер регистрирует нужный ему тип управления буферами для операций чтения и записи в объекте «устройство», который представляет устройство. Операции управления вводом-выводом на устройстве (выполняемые NtDeviceIoControlFile) задаются определенными в драйвере управляющими кодами ввода-вывода. Управляющий код включает тип управления буферами со стороны диспетчера ввода-вывода при обработке IRP с данным кодом.

Когда вызывающие потоки передают запросы размером менее одной страницы (4 Кб на х86-процессорах), драйверы, как правило, используют буферизованный ввод-вывод, а для запросов большего размера — прямой. Буфер примерно равен размеру страницы, и операция копирования с применением буферизованного ввода-вывода приводит практически к тем же издержкам, что и прямой ввод-вывод, требующий блокирования памяти. Драйверы файловой системы обычно используют третий тип управления, так как при копировании данных из кэша файловой системы в буфер вызывающего потока это позволяет избавиться от издержек, связанных с управлением буферами. Ho большинство драйверов не использует этот вид управления из-за того, что указатель на буфер вызывающего потока действителен лишь на то время, пока выполняется этот поток. Если драйверу нужно передать данные с устройства (или на устройство) при выполнении DPC-процедуры или ISR, он должен позаботиться о доступности данных вызывающего потока из контекста любого процесса, а значит, у буфера должен быть системный виртуальный адрес.

Драйверы, использующие ввод-вывод без управления для доступа к буферам, которые могут быть расположены в пользовательском пространстве, должны проверять, что адреса буфера действительны и не ссылаются на память режима ядра. Если они этого не делают, появляется вероятность краха системы или уязвимости в системе защиты, так как приложения получают доступ к памяти режима ядра или возможность внедрения своего кода в ядро. Функции ProbeForRead и ProbeForWrite, которые ядро предоставляет драйверам, проверяют, полностью ли умещается буфер в пользовательской части адресного пространства. Чтобы избежать краха из-за ссылки на недопустимый адрес, драйверы могут обращаться к буферам пользовательского режима из кода обработки исключений (блоков try/except), который перехватывает любые попытки доступа по неправильным адресам и транслирует их в коды ошибок для передачи приложению.

Запрос ввода-вывода к одноуровневому драйверу

B этом разделе вы увидите, как обрабатывается запрос синхронного ввода-вывода к одноуровневому драйверу режима ядра. Такая обработка проходит в семь этапов.

1. Запрос на ввод-вывод передается через DLL подсистемы.

2. DLL подсистемы вызывает сервис NtWriteFile диспетчера ввода-вывода.

3. Диспетчер ввода-вывода создает IRP, описывающий запрос, и посылает его драйверу (в данном случае — драйверу устройства), вызывая свою функцию IoCallDriver.

4. Драйвер передает данные из IRP на устройство и инициирует операцию ввода-вывода.

5. Драйвер уведомляет о завершении ввода-вывода, генерируя прерывание.

6. Когда устройство завершает операцию и вызывает прерывание, драйвер устройства обслуживает прерывание.

7. Драйвер вызывает функцию IoCompleteRequest диспетчера ввода-вывода, чтобы уведомить его о завершении обработки IRP, и диспетчер ввода-вывода завершает данный запрос на ввод-вывод.

Эти семь этапов показаны на рис. 9-10.

Теперь, когда мы знаем, как инициируется ввод-вывод, рассмотрим обслуживание прерывания и завершение ввода-вывода.

Обслуживание прерывания
Перейти на страницу:

Похожие книги

1С: Управление небольшой фирмой 8.2 с нуля. 100 уроков для начинающих
1С: Управление небольшой фирмой 8.2 с нуля. 100 уроков для начинающих

Книга предоставляет полное описание приемов и методов работы с программой "1С:Управление небольшой фирмой 8.2". Показано, как автоматизировать управленческий учет всех основных операций, а также автоматизировать процессы организационного характера (маркетинг, построение кадровой политики и др.). Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, формировать разнообразные отчеты, выводить данные на печать. Материал подан в виде тематических уроков, в которых рассмотрены все основные аспекты деятельности современного предприятия. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов. Все приведенные в книге примеры и рекомендации основаны на реальных фактах и имеют практическое подтверждение.

Алексей Анатольевич Гладкий

Экономика / Программное обеспечение / Прочая компьютерная литература / Прочая справочная литература / Книги по IT / Словари и Энциклопедии