Самоучитель по программированию систем защиты

       

Ограничения, налагаемые на код с уровнем IRQL большим или равным DISPATCHJLEVEL



Ограничения, налагаемые на код с уровнем IRQL большим или равным DISPATCHJLEVEL



IRQL dispatchjevel имеет важное значение в Windows NT. Как уже говорилось выше, Диспетчер (планировщик) Windows NT получает запросы, чтобы выполнить

операцию перепланирования, на уровне IRQL dispatch_level. Этот факт имеет три важных следствия:

  • Любой поток с IRQL >= DISPATCH_LEVEL не подвержен механизму планирования.
  • Любой поток с IRQL >= DISPATCH_LEVEL не может использовать никакие функции ожидания Диспетчерских Объектов ядра с отличным от нуля временем ожидания.
  • Любой поток с IRQL >= DISPATCH_LEVEL не должен приводить к ошибкам отсутствия страниц памяти (что происходит при обращении к участку памяти, находящемуся йа выгруженной на диск странице памяти). Иными словами, на таких уровнях IRQL может быть использована только невыгружаемая память (nonpaged pool, организация памяти будет рассмотрена в следующем разделе).
  • Рассмотрим эти пункты более подробно.

    Так как Диспетчер выполняется на уровне IRQL DISPATCH_LEVEL, любая подпрограмма, которая выполняется на IRQL dispatchjevel или выше, не подчиняется приоритетному прерыванию (выгрузке). Таким образом, когда квант времени потока истекает, если этот поток выполняется в настоящее время на IRQL dispatch_level или выше, он продолжит выполняться, пока не попытается понизить IRQL текущего процессора ниже dispatchjevel. Это должно быть очевидно, так как исполнение на некотором уровне IRQL блокирует распознавание других событий, запрошенных на этом же или более низком уровне IRQL.

    Что может быть менее очевидно, так это то, что, когда код выполняется на уровне IRQL dispatch_level или выше, он не может ждать никакие диспетчерские объекты (Dispatcher Object - см. раздел «Механизмы синхронизации»), которые еще не переведены в сигнальное состояние (состояние «свободен»). Таким образом, например, код, выполняющийся на уровне IRQL dispatch_level или выше, не может ожидать установки объектов событие или мьютекс. Так происходит потому, что действие освобождения процессора (которое происходит, когда поток переходит в режим ожидания события) требует (по крайней мере, концептуально) запуска Диспетчера.
    Однако, если подпрограмма выполняется на уровне dispatch_level или выше, прерывание уровня dispatchjevel (по которому запускается Диспетчер) будет маскировано и, следовательно, распознано не сразу. В результате происходит возврат обратно к коду, который вызвал операцию ожидания!

    Еще менее очевидным может быть тот факт, что код, выполняющийся на уровне IRQL dispatch_level или выше не должен приводить к ошибкам отсутствия страниц (page faults). Это означает, что любой такой код сам должен быть невыгружаемым, и должен обращаться только к невыгружаемым структурам данных. В основном это объясняется тем, что код, выполняющийся на IRQL dispatch_level или выше не может ждать освобождения диспетчерского объекта. Таким образом, даже если бы страничный запрос был обработан, поток с ошибкой отсутствия страницы не мог бы быть приостановлен, пока необходимая страница читалась с диска.


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