Структура драйвера. Ограничения, налагаемые на драйвер.
Контекст исполнения и уровень IRQL
Говоря о точках входа в драйвер, необходимо отметить контекст, при котором эти точки входа могут быть вызваны.
Вначале необходимо определиться с тем, что мы подразумеваем под контекстом исполнения?
Контекст исполнения определяется двумя составляющими:
- исполняемый в настоящее время поток (контекст планирования потока – thread scheduling context);
- контекст памяти процесса, которому принадлежит поток.
Текущий контекст исполнения может принадлежать одному из трех классов:
- контекст процесса "System" (далее – системный контекст);
- контекст конкретного потока и процесса;
- контекст случайного потока и процесса (далее – случайный контекст).
Различные точки входа в драйвер могут вызываться в контексте, принадлежащем одному из этих классов.
DriverEntry всегда вызывается в системном контексте.
Диспетчерские функции для драйверов верхнего уровня (то есть получающих запрос от прикладных программ) вызываются в контексте инициирующего запрос потока.
Диспетчерские функции драйверов остальных уровней, получающие запрос от драйвера верхнего уровня, вызываются в случайном контексте.
Все точки входа, связанные с сериализацией запросов ввода/вывода или с обработкой прерываний и DPC, вызываются в случайном контексте.
DriverEntry всегда вызывается на IRQL, равным PASSIVE_LEVEL.
Диспетчерские точки входа вызываются на IRQL, равным PASSIVE_LEVEL или APC_LEVEL.
Вызов отложенных процедур – на DISPATCH_LEVEL.
Функции обработки прерываний – на одном из DIRQL.
Ограничения, налагаемые на драйвер
- Драйвер режима ядра не может использовать API пользовательского уровня или стандартные библиотеки времени исполнения языка С. Можно использовать только функции ядра.
- Драйвер не может осуществлять операции с числами с плавающей точкой. Попытка сделать это может вызвать аварийную остановку системы. Причина – в основе реализации архитектуры ММХ. Не вдаваясь в подробности можно сказать, что в этой архитектуре для обозначения регистров ММХ использованы те же обозначения, что и для использования регистров FPU. Переключение между использованием регистров MMX/FPU, производимое на пользовательском уровне, невидимо для драйвера.
- Драйвер не может манипулировать физической памятью напрямую. Однако он может получить виртуальный адрес для любого физического адреса и манипулировать им.
- Код драйвер не должен долгое время работать на повышенных уровнях IRQL. Другие ограничения можно посмотреть в [Developing Windows NT Device Driver, chapter 5, Driver Limitation].
Последующие разделы будут посвящены описанию различных точек входа драйвера.