Це складно. ;)
Ні, справді, так і є.
IRQL означає "Рівень запиту переривання". Це число, яке становить від 0 до 31 в системах Windows x86 і від 0 до 15 для систем x64. Він представляє "важливість" завдання в режимі ядра стосовно інших завдань режиму ядра.
IRQL - це визначений Windows стан процесора - не процесу чи потоку -, який вказує Windows, чи може все, що робить цей процесор, може бути перервано іншими завданнями. Якщо у новому завданні (наприклад, у звичайній службі переривання) є більш високий IRQL, ніж у поточному IRQL процесора, то так, воно може перервати поточне завдання; інакше ні. У багатопроцесорній системі кожен процесор має власну IRQL. Сюди входять "Логічні процесори", створені гіперточкою.
(Я використовую слово "важливість", а не "пріоритет", тому що "пріоритет" у Windows стосується пріоритетів потоку, а IRQL - щось інше. На відміну від пріоритетів потоку, завдання ядра в тому ж IRQL не розрізані часом, а IRQL - не " t підлягають автоматичному прискоренню та згасанню.)
(Я також повинен зазначити, що термін "завдання ядра" тут не є офіційним. 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 вище, ніж у всіх "звичайних" апаратних пристроїв.
IRQLs 2 і вище використовуються для завдань ядра, які не викликаються апаратними перериваннями, але під час яких нормальне планування потоку, включаючи очікування, не може відбутися. Таким чином, як тільки процесор знаходиться на IRQL 2 або вище, жоден контекстний комутатор потоку не може відбуватися на цьому процесорі, поки IRQL не опуститься нижче 2.
Код режиму користувача завжди знаходиться на IRQL 0. Код режиму ядра може працювати в будь-якому IRQL від 0 до будь-якого максимуму. IRQL 1 - особливий випадок; це лише режим ядра, але не впливає на планування, і це справді більше стан потоку, ніж процесор - він зберігається і відновлюється, наприклад, під час контекстних комутацій потоків.
З метою підтримання різних гарантій серіалізації більшість винятків (такі як поділ на нуль або порушення доступу до пам'яті, як помилки сторінки) просто не піддаються обробці на IRQL 2 або вище. (IRQL 2 btw прийнято називати "рівнем відправки" або "рівнем DPC".)
І тепер ми можемо нарешті пояснити цей код помилок!
Найпоширеніший випадок IRQL_NOT_LESS_OR_EQUAL пов'язаний з помилкою сторінки (спроба отримати доступ до віртуальної адреси "не резидент") або порушенням доступу до пам'яті (спроба запису на сторінку лише для читання або доступу до сторінки, яка не визначена взагалі), що відбувається на IRQL 2 або вище.
Якщо такі винятки підняті на IRQL 0 або 1, вони можуть бути "оброблені" або за допомогою системного коду (наприклад, обробник помилок сторінки), або обробника винятків, наданого розробником. Однак більшість винятків взагалі не обробляються, якщо вони сталися на IRQL 2 або вище.
Отже ... код помилки означає "виняток типу, який можна обробляти лише в IRQL 0 або 1, стався, коли IRQL був на рівні 2 або вище". тобто "не менше або дорівнює 1". Дивне формулювання, але воно є.
Є кілька інших речей, які можуть викликати цю помилку, і значення, для якого IRQL не менше або рівне, не завжди є 1, але вони трапляються лише рідко. Документація WinDBG перераховує їх.