Программирование драйверов Windows

       

Доступ к областям памяти пользовательских приложений


В момент, когда программный код приложений, выполняющийся в пользовательском режиме, делает запрос на ввод/вывод, то он передает адрес буферной области, которая содержит данные (или предназначена для их получения) и размещена в пользовательском адресном пространстве. Поскольку адреса пользовательского режима указывают в нижнюю часть (ниже 2 Гбайт для обычных версий ОС) страничных таблиц, драйвер должен рассматривать возможность того, что страничные таблицы могут (и будут) меняться до окончания обработки запроса. Это может произойти в случае, если рабочая ветвь кода драйвера выполняется в контексте прерывания или в контексте потока, выполняющегося в режиме ядра. Нижняя часть страничных таблиц меняется при каждом переключении процесса (process switch). Таким образом, далеко не весь программный код драйвера может рассчитывать на то, что все адреса пользовательского режима будут верны и применимы в течение всего времени обработки запроса.

Хуже того, пользовательский буфер может быть и вовсе перемещен из оперативной памяти на жесткий диск в системный swap-файл. Области памяти, выделенные пользовательским приложениям, всегда рассматриваются операционной системой в качестве кандидатов для сброса на диск, если системе не хватает ресурсов оперативной памяти для других процессов.

Общим правилом является то, что виртуальная память пользовательских приложений является страничной, а к такой памяти нельзя обращаться из программного кода, выполнение которого происходит на IRQL уровне DISPATCH_LEVEL или выше. Этому постулату следовать необходимо по той простой причине, что работа по возвращению страницы памяти из swap-файла (в случае, если она туда попала) в оперативную память выполняется службами, которым для завершения этой операции могут потребоваться устройства, работающие при DIRQL более низком, чем IRQL кода-инициатора обращения к этой "неудачной" странице виртуальной памяти.



Содержание раздела