IRQL_NOT_LESS_OR_EQUAL 到底是什麼?什麼是IRQL?哪些東西用IRQL?為什麼它需要小於或等於?什麼會導致它不小於或等於?為什麼作業系統不能從不小於或等於的情況中恢復? IRQL 只影響 Windows 嗎?
這個錯誤似乎是很常見。我不是尋求幫助,我是在尋求解釋。
答案1
情況很複雜。 ;)
不,確實如此。
IRQL 代表「中斷請求等級」。它是一個數字,在 Windows x86 系統上範圍為 0 到 31,在 x64 系統上範圍為 0 到 15。它表示內核模式任務相對於其他核心模式任務的「重要性」。
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 2 或更高層級的其他任務執行完成。相同的IRQL 將在同一處理器上啟動。它可能會被更高 IRQL 的任務中斷(該任務又可能被更高 IRQL 的任務中斷,等等),但是當更高 IRQL 的任務完成時,控制權將返回到它中斷的任務。
IRQL 主要是一個序列化機制。 (很多人說“同步”,但我更喜歡這個詞,因為它更準確地描述了結果。)它的目的是幫助保證同一CPU 上的多個任務訪問某些共享資源(主要是作業系統核心空間中的共享資料結構)不允許以可能破壞這些結構的方式互相干擾。
例如,Windows核心中的大量數據,特別是記憶體管理資料和執行緒調度程序使用的數據,“系列化”IRQL 2。如果更高 IRQL 的任務嘗試寫入此類數據,則可能會導致損壞,因為它可能中斷了 IRQL 2 任務,而該任務可能正處於對相同資料的讀取-修改-寫入週期的中間。因此,更高 IRQL 的任務根本不允許這樣做。
較高IRQL 的任務主要是裝置驅動程式的中斷服務例程,因為所有裝置的中斷都發生在IRQL > 2 時。驅動活動。它的IRQL高於所有“普通”硬體設備。
IRQL 2 及更高版本用於不由硬體中斷觸發但在此期間不能發生正常執行緒調度(包括等待)的核心任務。因此,一旦處理器處於 IRQL 2 或以上,該處理器上就不會發生執行緒上下文切換,直到 IRQL 降至 2 以下。
使用者模式程式碼始終處於 IRQL 0。 IRQL 1 是一個特例;它只是核心模式,但對調度沒有影響,並且實際上更多的是線程的狀態而不是處理器的狀態 - 例如,它在線程上下文切換期間保存和恢復。
為了維持各種序列化保證,大多數異常(例如除以零,或記憶體存取違規(例如頁面錯誤))在 IRQL 2 或更高版本下根本無法處理。 (順便說一句,IRQL 2 通常稱為「調度等級」或「DPC 等級」。)
現在我們終於可以解釋這個錯誤檢查程式碼了!
IRQL_NOT_LESS_OR_EQUAL 最常見的情況是由於頁面錯誤(嘗試存取「非駐留」虛擬位址)或記憶體存取衝突(嘗試寫入唯讀頁面,或存取未定義的頁面)根本沒有),這發生在IRQL 2 或以上。
如果此類異常在 IRQL 0 或 1 處引發,則可以透過系統提供的程式碼(如頁面錯誤處理程序)或開發人員提供的異常處理程序來「處理」它們。但是,如果大多數異常發生在 IRQL 2 或更高級別,則根本無法處理。
所以...錯誤檢查代碼意味著「當 IRQL 為 2 或更高時,發生了只能在 IRQL 0 或 1 處理的類型的異常」。即“不小於或等於1”。奇怪的措辭,但確實如此。
還有一些其他事情可以觸發此錯誤檢查,並且 IRQL 不小於或等於的值並不總是 1,但它們很少發生。 WinDBG 文件列出了它們。