[Previous] [Next]

Другие процедуры драйвера

В дополнение к только что описанному базисному набору процедур, драйвер может содержать несколько вспомогательных функций.

Таймерные процедуры

Драйвер, которому нужно выполнять точный отсчет временных интервалов, должен использовать либо DPC процедуру IoTimer (которая, если она зарегистрирована должным образом, всегда вызывается один раз в секунду), либо Custom DPC процедуру для таймера (кратко была рассмотрена выше). В литературе последняя упоминается как CustomTimerDpc.

Процедура IoCompletion

Драйвер модели WDM, работающий внутри многослойной драйверной структуры, может испытывать потребность в том, чтобы его уведомляли, когда будет завершена обработка IRP запроса, посланного драйверу нижнего уровня. Для этой цели драйвер может зарегистрировать callback процедуру IoCompletion (так она называется в документации DDK), при помощи которой он может выполнять весьма впечатляющие трюки. В частности, драйвер может разбивать крупные операции ввода/вывода на более мелкие. Механизм достаточно прост: по окончании частичного переноса данных, управление оказывается в процедуре IoCompletion, которая тут же начинает следующий перенос данных. Регистрация этой callback процедуры выполняется при помощи вызова IoSetCompletionRoutine.

Процедура CancelRoutine

Драйвер должен учитывать возможность того, что какой-либо из IRP запросов (текущий или находящийся в состоянии ожидания обработки) может быть отменен. Простейшая ситуация, которая к этому ведет, возникает, когда пользовательское приложение, не дождавшись отклика от устройства и драйвера, попросту снимается при помощи диспетчера задач. Тем временем драйвер, будто ничего не случилось, пытается завершить порученные ему задачи. Диспетчер ввода/вывода выполняет удаление IRP запросов, находящихся в ожидании обработки, и мог бы сообщить об этом драйверу вызовом callback процедуры CancelRoutine (под таким именем она фигурирует в документации DDK), если бы тот зарегистрировал ее при помощи вызова IoSetCancelRoutine. Особенность применения этих процедур состоит в том, что при помощи вызова IoSetCancelRoutine можно назначать разные CancelRoutine процедуры для отслеживания разных экземпляров IRP пакетов. Более того, даже на разных уровнях работы драйвера можно заново определять процедуру CancelRoutine (необходимо только хранить указатели на интересующие IRP пакеты), а то и вовсе отменить отслеживание уничтожения IRP пакетов — указав NULL вместо адреса CancelRoutine при вызове IoSetCancelRoutine.

Другая ситуация удаления пакетов IRP, ожидающих обработки, возникает в случае, если пользовательское приложение применило вызов API функции CancelIo (см. заголовочный файл winbase.h или документацию MSDN). Правда, применение этого вызова требует, чтобы доступ к драйверу был получен с использованием флага FILE_FLAG_OVERLAPPED, а этот прием программисты применяют крайне редко. Подробнее о CancelRoutine см. в 9 главе.