Что именно представляет собой IRQL_NOT_LESS_OR_EQUAL?

Что именно представляет собой IRQL_NOT_LESS_OR_EQUAL?

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

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

решение1

Все сложно. ;)

Нет, это правда.

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 является одним из примеров того, что я называю здесь «задачей ядра»).

Performance Monitor показывает время, проведенное на IRQL 2, как "% DPC time", а время на IRQL > 2 — как "% interrupt time", независимо от того, было ли время фактически проведено в процедуре DPC или ISR или было результатом повышения IRQL с более низкого значения. Каждый из них является подмножеством того, что PerfMon показывает как "% privileged time" — что должно было быть помечено как "kernel mode time".

После запуска задачи ядра на уровне 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 перечисляет их.

Связанный контент