Это сложно. ;)
Нет, правда.
IRQL означает «Уровень запроса прерывания». Это число от 0 до 31 в системах Windows x86 и от 0 до 15 в системах x64. Он представляет «важность» задачи режима ядра относительно других задач режима ядра.
IRQL - это определяемое Windows состояние процессора, а не процесса или потока, которое указывает Windows, может ли то, что делает этот процессор, быть прервано другими задачами. Если новая задача (например, подпрограмма обработки прерываний) имеет более высокий IRQL, чем текущий IRQL процессора, то да, она может прервать текущую задачу; в противном случае нет. В многопроцессорной системе каждый процессор имеет свой собственный IRQL. Это включает в себя «логические процессоры», созданные с помощью гиперпоточности.
(Я использую слово «важность», а не «приоритет», потому что «приоритет» в Windows относится к приоритетам потоков, а IRQL - это нечто иное. В отличие от приоритетов потоков, задачи ядра в том же IRQL не разделены по времени, и IRQL не являются ' подвержены автоматическому увеличению и затуханию.)
(Я должен также упомянуть, что термин «задача ядра» здесь не является официальным. Windows на самом деле не называет эти вещи «задачами ядра», они не являются управляемыми объектами, как, например, процессы и потоки, и не имеют никакого отношения к задаче x86 » gates »и ни к чему, показанному в« Диспетчере задач ». Поскольку я (и другие) использую здесь термин,« задача режима ядра »действительно охватывает« все с определенным началом и концом, которое необходимо выполнить в режиме ядра на IRQL 2 или выше. "Подпрограмма обслуживания прерываний является одним примером" задачи режима ядра "; также как и подпрограмма DPC. Но другим примером может быть код в потоке режима ядра. Такие потоки начинаются с IRQL 0, но если часть кода повышениядля IRQL 2 или выше, что-то делает, а затем возвращается к предыдущему IRQL, часть кода с высоким IRQL является одним из примеров того, что я называю здесь «задачей ядра». )
Системный монитор отображает время, потраченное на IRQL 2 как «время% DPC», а время при IRQL> 2 как «время% прерывания», независимо от того, было ли время фактически потрачено в процедуре DPC или ISR или было результатом повышения IRQL из более низкое значение. Каждый из них является подмножеством того, что PerfMon показывает как «% привилегированное время», которое должно было быть помечено как «время режима ядра».
Как только задача ядра запускается на IRQL 2 или выше, она выполняется до завершения, прежде чем что-либо еще на том же IRQL будет запущено на том же процессоре. Она может быть прервана задачей с более высоким IRQL (которая, в свою очередь, может быть прервана задачей с более высоким IRQL и т. Д.), Но когда задачи с более высоким IRQL завершены, управление возвращается к задаче, которую оно прервало.
IRQL - это прежде всего механизм сериализации . (Многие говорят «синхронизация», но я предпочитаю это слово, поскольку оно более точно описывает результат.) Его цель - помочь гарантировать, что несколько задач на одном и том же ЦП, которые обращаются к определенным общим ресурсам - в основном, к общим структурам данных в пространстве ядра ОС - не разрешается прерывать друг друга таким образом, чтобы это могло повредить эти структуры.
Например, большое количество данных в ядре Windows, в частности данные управления памятью и данные, используемые планировщиком потоков, «сериализуются» на IRQL 2. Это означает, что любая задача, которая хочет изменить такие данные, должна выполняться на IRQL 2, когда это так. Если задача с более высоким IRQL пытается записать такие данные, это может привести к повреждению, поскольку оно могло прервать задачу IRQL 2, которая может находиться в середине цикла чтения-изменения-записи для тех же данных. Так что задачам с более высоким IRQL просто не разрешено это делать.
Задачи с более высоким IRQL - это в основном подпрограммы обслуживания прерываний драйверов устройств, поскольку прерывания всех устройств происходят при IRQL> 2. Это включает прерывание от микросхемы таймера на материнской плате, которая управляет хронометрированием и управляемой временем активностью в ОС. Его IRQL выше, чем у всех "обычных" аппаратных устройств.
IRQL 2 и выше используются для задач ядра, которые не запускаются аппаратными прерываниями, но во время которых не может происходить нормальное планирование потоков, включая ожидание. Таким образом, если процессор находится на уровне IRQL 2 или выше, переключение контекста потока на этом процессоре не может произойти, пока IRQL не опустится ниже 2.
Код режима пользователя всегда имеет значение IRQL 0. Код режима ядра может работать на любом уровне IRQL от 0 до максимального значения. IRQL 1 - особый случай; это только режим ядра, но он не влияет на планирование и в действительности является скорее состоянием потока, чем процессора - он сохраняется и восстанавливается, например, при переключении контекста потока.
Чтобы поддерживать различные гарантии сериализации, большинство исключений (такие как деление на ноль или нарушения доступа к памяти, такие как сбои страниц) просто не могут обрабатываться на IRQL 2 или выше. (Кстати, IRQL 2 обычно называют «уровнем диспетчеризации» или «уровнем DPC».)
И теперь мы можем наконец объяснить этот код проверки на ошибки!
Наиболее распространенный случай IRQL_NOT_LESS_OR_EQUAL связан с ошибкой страницы (попытка доступа к «нерезидентному» виртуальному адресу) или нарушением доступа к памяти (попытка записи на страницу только для чтения или на страницу, которая не определена). вообще), что происходит на IRQL 2 или выше.
Если такие исключения возникают при IRQL 0 или 1, они могут быть «обработаны» либо системным кодом (например, обработчиком ошибок страницы), либо обработчиком исключений, предоставленным разработчиком. Однако большинство исключений не могут быть обработаны вообще, если они произошли в IRQL 2 или выше.
Итак ... код проверки на наличие ошибок означает «исключение типа, которое может быть обработано только при IRQL 0 или 1, когда IRQL был на уровне 2 или выше». то есть "не меньше или равно 1". Странная формулировка, но она есть.
Есть несколько других вещей, которые могут вызвать эту проверку, и значение, которое IRQL не меньше или равно, не всегда 1, но они встречаются очень редко. Документация WinDBG перечисляет их.