13

Что именно такое IRQL_NOT_LESS_OR_EQUAL? Что такое IRQL? Какие вещи используют IRQL? Почему оно должно быть меньше или равно? Что заставило бы это не быть меньше или равным? Почему ОС не может восстановиться после того, как она не станет меньше или равна? IRQL влияет только на Windows?

Эта ошибка кажется довольно распространенной. Я не прошу помощи, я прошу объяснений.

1 ответ1

19

Это сложно. ;)

Нет, правда.

IRQL означает "Уровень запроса прерывания". Это число от 0 до 31 в системах Windows x86 и от 0 до 15 в системах x64. Он представляет "важность" задачи режима ядра относительно других задач режима ядра.

IRQL - это определяемое Windows состояние процессора, а не процесса или потока, которое указывает Windows, может ли то, что делает этот процессор, быть прервано другими задачами. Если новая задача (например, подпрограмма обработки прерываний) имеет более высокий IRQL, чем текущий IRQL процессора, то да, она может прервать текущую задачу; в противном случае нет. В многопроцессорной системе каждый процессор имеет свой собственный IRQL. Это включает в себя "логические процессоры", созданные с помощью гиперпоточности.

(Я использую слово "важность", а не "приоритет", потому что "приоритет" в Windows относится к приоритетам потоков, а IRQL - это нечто другое. В отличие от приоритетов потоков, задачи ядра в одном и том же IRQL не разделены по времени, а IRQL не подвержены автоматическому увеличению и затуханию. )

(Следует также упомянуть, что термин "задача ядра" здесь не является официальным. В действительности Windows не называет эти вещи "задачами ядра", они не являются управляемыми объектами, как, например, процессы и потоки, и не имеют никакого отношения ни к "воротам задач" x86, ни к чему-либо, отображаемому в "Диспетчере задач". Поскольку я (и другие) использую здесь термин, "задача режима ядра" действительно охватывает «все с определенным началом и концом, которое необходимо выполнить в режиме ядра с 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 перечисляет их.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .