- IRQL определя приоритетите на изпълнение и маскира прекъсванията по ниво, над DISPATCH той командва IRQL, а не приоритета на нишката.
- Лос BSOD 0xA/0xD1 обикновено се причиняват от достъп до пейджируема или невалидна памет при висок IRQL и неправилни адреси или пейджируем код.
- WinDbg и Driver Verifier са ключови: използвайте !analyze, !irql, ln, .trap, !pool, !address и проверете параметри 1, 3 и 4.
- En шофьори, предотвратява грешки на страниците при висок IRQL, използва нестранирана памет и заключвания на spin-a; за потребителя, актуализира/изолира проблемни драйвери.
Ако някога сте виждали син екран със съобщения като IRQL_NOT_LESS_OR_EQUAL o DRIVER_IRQL_NOT_LESS_OR_EQUAL, вероятно сте се натъквали на концепция, която е малко позната извън света на драйверите: IRQL (ниво на заявка за прекъсване). Windows, това ниво на приоритет на прекъсванията има предимство пред приоритета на нишките, когато системата е над определен праг, и това има директни последици за стабилността.
В следващите редове ще откриете Una пълно ръководство и на испански от Испания за това какво е IRQL, как работи, защо се появяват сини екрани, как да се диагностицира проблемът с WinDbg и какво да се направи, независимо дали сте потребител, който среща грешката, или разработвате драйвери в режим на ядрото. Нека се заемем с работата.
Какво е IRQL (ниво на заявка за прекъсване) в Windows?
В Windows, IRQL определя приоритета на железария на която работи процесорът във всеки един момент. В рамките на Windows Driver Model (WDM), код, изпълняващ се при нисък IRQL, може да бъде прекъснат от код, изпълняващ се при по-висок IRQL. Всъщност, на един многоядрен компютър, всеки процесор може да бъде с различен IRQL, което усложнява синхронизацията.
Има едно ключово правило: Когато процесорът работи на IRQL над PASSIVE_LEVEL, той може да бъде изпреварен само от активност на още по-висок IRQL.Това организира съвместното съществуване между потребителски код, функции на ядрото, отложени повикващи (DPC) и рутини за обслужване на прекъсвания на устройства (ISR).
Нива и приоритети: PASSIVE_LEVEL, APC_LEVEL, DISPATCH_LEVEL и DIRQL
Като цяло, На x86 се използват IRQL стойности между 0 и 31; на x64, между 0 и 15.Практическото значение е същото: IRQL 0 (PASSIVE_LEVEL) е мястото, където се изпълняват нормален потребителски код и много функции на драйвера; APC и грешки на страниците Те обикновено са съпоставени с IRQL 1 (APC_LEVEL); IRQL 2 (DISPATCH_LEVEL) обхваща планировчика на нишки и DPC. Над DISPATCH_LEVEL са нивата, запазени за прекъсвания на устройства (известни като DIRQL) и други вътрешни приложения, като например HIGH_LEVEL.
В екосистемата на водача, Много често срещани рутини се изпълняват на DISPATCH_LEVELнапример, DPC и StartIo. Този дизайн гарантира, че докато една от тях докосва вътрешни опашки или други споделени ресурси, друга рутина на същото ниво не я изпреварва на този процесор, защото правилото за изпреварване позволява прекъсвания само на по-високи нива.
Между DISPATCH_LEVEL и профилиращите/високите нива има място за хардуерни прекъсвания на всяко устройство (DIRQL)IRQL на устройството определя неговия приоритет спрямо другите устройства. WDM драйверът получава този IRQL по време на IRP_MJ_PNP с IRP_MN_START_DEVICE. Този IRQL на устройството не е глобална, фиксирана стойност, а по-скоро стойност, свързана с конкретна линия за прекъсване.
IRQL срещу приоритет на нишката
Препоръчително е да не се бъркат понятията: Приоритетът на нишките определя кога планировчикът ще изпреварва и коя нишка ще се изпълни.; IRQL контролира какъв тип дейност може да се изпълнява и кои прекъсвания са маскирани. Над DISPATCH_LEVEL няма превключване на нишки: IRQL контролира, а не приоритетът на нишките.
IRQL и пейджинг: Какво не трябва да правите
Незабавен ефект от повишаването на IRQL е, че системата не може да обработва грешки на страницитеЗлатно правило: код, изпълняван на или над DISPATCH_LEVEL, не може да причинява грешки на страниците. На практика това означава, че тези рутини и данните, до които те докосват трябва да се намира в непейджирана паметОсвен това, някои помощни програми на ядрото ограничават употребата си въз основа на IRQL: например, KeWaitForSingleObject
DISPATCH_LEVEL може да се извика само ако не блокирате (нулево време за изчакване), а за ненулеви времеви изчаквания трябва да сте под DISPATCH_LEVEL.
Имплицитен и експлицитен контрол на IRQL
През повечето време, самата система извиква вашите рутини при правилния IRQL за това, което трябва да правят. Рутините за изпращане на IRP се изпълняват на PASSIVE_LEVEL (те могат да блокират или извикат всеки помощник), StartIo и DPC се изпълняват на DISPATCH_LEVEL за защита на споделените опашки, а ISR се изпълняват на DIRQL.
Ако трябва да го контролирате изрично, Можете да увеличите и намалите IRQL с KeRaiseIrql
y KeLowerIrql
Има един много използван пряк път: KeRaiseIrqlToDpcLevel()
връща предишния IRQL и ви оставя на DISPATCH_LEVEL. Важно: Никога не понижавайте IRQL под стойността, която е била, когато системата ви е извикала; нарушаването на тази синхронизация може да отвори много сериозни прозорци за състезание.
Грешки на син екран, свързани с IRQL: IRQL_NOT_LESS_OR_EQUAL и DRIVER_IRQL_NOT_LESS_OR_EQUAL
Две класически проверки за грешки, свързани с тези проблеми, са IRQL_НЕ_ПО-МАЛКО_ИЛИ_РАВНО (0xA) y DRIVER_IRQL_NOT_LESS_OR_EQUAL (0xD1)И двете показват опит за достъп до пейджируем (или невалиден) адрес при IRQL, който е твърде висок. Това обикновено се дължи на драйвери, използващи неправилни адреси, разреференциране на лоши указатели или изпълнение на пейджируем код на неподходящи нива.
В конкретния случай на DRIVER_IRQL_NOT_LESS_OR_EQUAL (0x000000D1), параметрите са много информативни: 1) адрес на посочената памет; 2) IRQL в този момент; 3) тип достъп (0 четене, 1 запис, 2/8 изпълнение); 4) адрес на инструкцията, която е посочена паметта. С дебъгера можете да използвате ln
на параметър 4 за избройте най-близкия символ и разберете каква функция се е изпълнявала.
Често срещани причини, които трябва да имате предвид
Отвъд специфичния код, има и повтарящи се модели. Разреференциране на невалиден указател към DISPATCH_LEVEL или по-висока стойност Това е сигурна рецепта за бедствие. Достъпът до данни, които могат да се преобразуват в страници, на това ниво или изпълнението на код, който може да се преобразува в страници (напр. функция, маркирана като преобразувана в страници), също задейства проверката за грешки.
Други често срещани случаи включват извикване на функция в друг драйвер, който вече е бил изтеглен (висящ указател на функция) или индиректно извикан чрез невалиден указател на функция. Често, ако системата е в състояние да идентифицира модул, ще видите името му на самия син екран и той също е записан в KiBugCheckDriver
, достъпен с dx KiBugCheckDriver
от WinDbg.
Практичен детайл: В повечето D1/A, истинският проблем не е самият IRQL., а по-скоро посоченият адрес на паметта. Ето защо параметри 1, 3 и 4 са от решаващо значение за фокусиране на диагнозата.
Диагностика с WinDbg: Полезни команди и четене на параметри
За да работим по тези случаи, WinDbg е ключовият инструменти ако BSOD споменава ntoskrnl.exe Тази информация предоставя много насоки относно това дали грешката е в подсистемата на ядрото. Започнете с !analyze -v
за да получите обобщение на проверката за грешки, стека и, ако имате късмет, съответния модул. Ако дъмпът включва кадър за заснемане, .trap
ви поставя в контекста на повредения процесор.
Лос команди купчина като k
, kb
, kc
, kd
, kp
, kP
, kv
Те ви показват различни нива на детайлност на обратната трасировка. С ln
на параметър 4 можете да пропуснете към инструкцията, която е цитирала паметта и вземете близкия символ. И ако подозирате, че нивото на приоритет се изпълнява преди прекъсването, !irql
показва ви запазения IRQL за целевия процесор (напр. DISPATCH_LEVEL).
За да се анализира посоката на параметър 1, !pool
Ще ви каже дали принадлежи към пейджиран пул; !address
y !pte
задълбочете се в картографирането на паметта на тази област. Можете да използвате командите за показване на паметта да се провери съдържанието, до което е направен опит за достъп. Накрая, u
, ub
, uu
позволяват ви да разглобите около адреса на параметър 4.
Не забравяйте lm t n
за да се изброят заредените модули y !memusage
за общото състояние на паметта. Ако KiBugCheckDriver
има нещо, dx KiBugCheckDriver
Ще върне името на Unicode модула: в типичен пример, „Wdf01000.sys“ е бил видян като драйвер, участващ по време на проверката за грешки.
Системни инструменти: Проверка на драйвери, Преглед на събития и Диагностика
El Проверка на драйвери Изследва поведението на драйверите в реално време и принуждава грешки, когато открие неправилно използване на ресурси (като например пула), като генерира изключение, за да изолира проблемната област от кода. Стартира се с verifier
от командния ред и е препоръчително да изберете възможно най-малкия набор от драйвери, за да избегнете добавянето на твърде много режийни разходи.
Ако не виждате себе си с WinDbg, прилагат основни меркиПроверете системния дневник в Event Viewer за грешки, сочещи към конкретно устройство/драйвер; актуализирайте или деактивирайте драйвера, цитиран от синия екран; проверете съвместимостта на хардуера с вашата версия на Windows; и използвайте Windows Memory Diagnostic, ако подозирате RAM памет. Тези действия, макар и прости, те решават голям брой случаи.
Случаи от реалния живот: Когато BSOD-ите изглеждат случайни
Потребител с Windows 10 Pro (процесор AMD Ryzen 5 3400G, GPU NVIDIA GeForce GTX 1660 Ti и платка Gigabyte B450 AORUS PRO WIFI, 16 GB RAM) получаваше периодични екрани „IRQL_LESS_OR_NOT_EQUAL“. Вече бях актуализирал основните драйвери (мрежа, графика), инсталирал всички актуализации на Windows и стартирал инструмента за памет, всичко това без да открия никакви проблеми.
В подобни сценарии, Следващата стъпка е да се анализират дъмповете с WinDbg и търсете модели: процеси, които се случват, когато пада (например explorer.exe
), модули за графичен интерфейс (win32kfull.sys
) и функции като xxxProcessNotifyWinEvent
появяващи се в стека. Въпреки че този модул е за Windows, причината често е драйвер на трета страна (графика, вход, наслагване, карти за заснемане), който използва памет с неподходящ IRQL и повредата възниква в win32k
.
Практическата препоръка тук е временно деактивиране на софтуера за наслагване (заснемане, GPU OSD), агресивни софтуерни периферни драйвери (мишки/клавиатури с макроси) и бета версии на графични драйвери и стеснете кръга. Използването на Driver Verifier при заподозрени може да помогне за стесняване на проблема с по-ясен стек.
Много често срещан мрежов модел: ndis.sys не винаги е виновникът
Друг типичен случай: екранна снимка с ndis.sys (мрежовият слой на Windows). На реален компютър системата би се сринала веднага след стартиране. Практическото решение беше да се стартира в Безопасен режим без мрежови функции, отворете Мениджър на устройства и деактивирайте адаптерите под „Мрежови адаптери“, за да изолирате проблема.
В този отбор имаше Realtek PCIe GBE Family контролер и Atheros AR5007GЧрез деактивиране и на двете беше установено, че истинската причина е athrx.sys
(Атерос), въпреки че синият екран спомена ndis.sys
Дъмпът потвърди това: стекът премина през ndis!NdisFreeTimerObject
но виновният модул беше athrx.sys
Последната корекция беше Деинсталирайте устройството и инсталирайте актуализирани официални драйвери От уебсайта на производителя на Atheros. Поука: Модулът, цитиран в BSOD, може да е част от засегнатата подсистема, а не от източника.
Типичен отговор на поддръжката и бързи стъпки за потребителите
В искрен обмен на подкрепа, техник отговори: „Извинявам се за неудобството. Възможно е проблемът да е с драйвер, памет или антивирусна програма. Моля, актуализирайте драйверите си и ако проблемът продължава, изпълнете диагностиката на паметта.“Това е основен, но валиден съвет; ако обаче грешките продължават, е добра идея да се продължи с Verifier и да се направи анализ на дъмп файловете.
За нетехнически потребители, разумен протокол би бил: 1) Проверете системните събития, 2) Актуализирайте ключови драйвери (чипсет/мрежа/графика), 3) Проверете RAM паметта с интегрирания инструмент, 4) тест ботуш чисто без софтуер на трети страни, който вмъква куки в ядрото/GUI, и 5) използвайте Verifier за драйвери на трети страни, ако нищо не е ясно.
Най-добри практики за разработчици на драйвери
Ако разработвате и попаднете на D1/A, проверете дали изпълняваната рутина не е маркирана като страницаируема Не извиквайте функции за пейджиране, докато се изпълняват на ниво DISPATCH_LEVEL или по-високо. Това включва избягване на препратки към данни в пейджираните секции и спазване на IRQL ограниченията за помощните програми на ядрото, описани в DDK.
За да синхронизирате споделени данни, прилагайте правилото „винаги осъществявайте достъп до споделените данни с еднакво високо IRQL ниво“ и използвайте spin locks, когато е уместно. При многопроцесорни системи, IRQL сам по себе си не гарантира изключване между различните процесори; spin locks повишават IRQL (до DISPATCH_LEVEL) и координират достъпа между ядрата. Ако е необходимо да работите с чувствителни хардуерни регистри, KeSynchronizeExecution
помага ви да изпълнявате критични секции на правилния DIRQL.
Когато планът изисква повишаване на IRQL, САЩ KeRaiseIrqlToDpcLevel
за DISPATCH_LEVEL или KeRaiseIrql
внимателно, запазвайки предишния IRQL и възстановявайки го точно с KeLowerIrql
Слезте под входния IRQL, дори само за миг, Това е сериозна грешка в синхронизацията.
Връзка с прекъсванията и хардуера
IRQL е механизмът, чрез който Windows заповедите прекъсват приоритетите и определени вътрешни задачиНа архитектурно ниво, това е свързано с понятия като „Прекъсване“, „Обработчик на прекъсвания“ или „Ниво на приоритет на прекъсване“, а на класическите платформи и с... Програмируем контролер за прекъсване (PIC)В други системи, контролът на приоритетите се изразява чрез механизми като spl en Unix; общата идея е същата: кой може кого да прекъсне.
Съвети за разширено отстраняване на грешки
В дъмпове, където стекът сочи към win32kfull!xxxProcessNotifyWinEvent
с проверка за грешки 0xA/0xD1, проверете контекста с .process
y .thread
(ако е възможно), разгледайте процеси като explorer.exe
en !process 0 1
и проверете наслагванията и драйверите за взаимодействие с графичния потребителски интерфейс. Много пъти проблемът Това е памет, повредена от трета страна, която се появява по този маршрут.
Не забравяйте да проверите IRQL с !irql
и контраст: ако сте на DISPATCH_LEVEL (2) и параметър 3 показва четене/запис/изпълнение На страница с възможност за странициране вече имате представа защо е паднала. Закръглете тази представа с ln
в параметър 4, за да се получи специфичната функция.
разбирам Какво е IRQL? и как се вписва в изпълнението на ядрото помага за отделяне на шума от сигналите. Ако сте потребител, фокусирайте се върху драйвери и хардуер (с Verifier, събития и тестове по подразбиране). Ако разработвате, стриктно спазвайте правилата за IRQL, непейджирана памет и синхронизация със spin locks. С правилните инструменти (WinDbg, Verifier) и внимателно четене на параметри (1, 3 и 4), Тези проверки за грешки вече не са загадка и те се превръщат в проблеми, които могат да бъдат решени методично.
Страстен писател за света на байтовете и технологиите като цяло. Обичам да споделям знанията си чрез писане и това е, което ще направя в този блог, ще ви покажа всички най-интересни неща за джаджи, софтуер, хардуер, технологични тенденции и много други. Моята цел е да ви помогна да се ориентирате в дигиталния свят по лесен и забавен начин.