Предварительная обработка в драйвере
Как было сказано ранее, каждый драйвер в своей процедуре DriverEntry производит заполнение специального массива, указатель на который передается в эту процедуру из Диспетчера ввода/вывода. Таким образом, драйвер выполняет регистрацию своих процедур. После заполнения массива адресами точек входа в процедуры драйвера, в распоряжении Диспетчера ввода/вывода оказывается таблица процедур для обслуживания запросов с поддерживаемыми функциональными кодами (индексом в этой таблице как раз и являются коды обрабатываемых запросов IRP_MJ_Xxx). Используя функциональные коды запросов, Диспетчер ввода/вывода ориентируется в этой таблице и привлекает к работе необходимые процедуры драйвера. Вызванная таким образом процедура решает (должна решать) следующие задачи:
Выполняет дополнительную проверку параметров входящего запроса. Драйвер может устанавливать зависящие от устройства ограничения, которые не могут быть известны Диспетчеру ввода/вывода. Например, пользователь может затребовать передачу большого объема данных, который превышает возможности обслуживаемого устройства (или драйвера).
В случае, если запрос не требует работы с физическим устройством (например, считывание 0 байт данных), то вызываемая драйверная процедура может завершить обработку и "отправить" IRP пакет обратно Диспетчеру ввода/вывода, пометив его как обработанный.
В случае, если запрос требует для завершения обработки реального обращения к обслуживаемому физическому устройству, рабочая процедура может пометить IRP пакет как незавершенный (pending). Таким образом, Диспетчеру ввода/вывода сообщается, что необходимо поместить в очередь запрос на вызов процедуры StartIo как только устройство освободится — возможно, что устройство еще обрабатывает предыдущий запрос. Вообще говоря, этап общения с устройством может быть реализован весьма экзотическими приемами, тут как раз место, где фантазия разработчиков разыгрывается не на шутку.
Содержание раздела