- IRQL は実行の優先順位を定義し、レベルによって割り込みをマスクします。DISPATCH より上では、スレッドの優先順位ではなく IRQL をコマンドします。
- たくさん BSOD 0xA/0xD1 は通常、高い IRQL でのページ可能または無効なメモリへのアクセス、および不正なアドレスまたはページ可能コードによって発生します。
- WinDbg と Driver Verifier が重要です。!analyze、!irql、ln、.trap、!pool、!address を使用して、パラメーター 1、3、4 を調べます。
- En ドライバー高い IRQL でのページ フォールトを防止し、非ページ メモリとスピン ロックを使用します。ユーザーにとっては、問題のあるドライバーを更新/分離します。
次のようなメッセージが表示されたブルースクリーンを見たことがあるなら IRQL_NOT_LESS_OR_EQUAL o DRIVER_IRQL_NOT_LESS_OR_EQUALおそらく、ドライバー以外ではあまり知られていない概念、IRQL(割り込み要求レベル)について聞いたことがあるでしょう。 Windowsシステムが特定のしきい値を超えた場合、このレベルの割り込み優先度はスレッド優先度よりも優先され、これは安定性に直接影響を及ぼします。
次の行には A 完全なガイド スペインからスペイン語でIRQLとは何か、どのように機能するかについてブルースクリーンが発生する理由、WinDbgで問題を診断する方法、そしてエラーが発生しているユーザーやカーネルモードドライバを開発しているユーザーの対処法について説明します。それでは、早速始めましょう。
Windows の IRQL (割り込み要求レベル) とは何ですか?
Windowsでは、 IRQLは優先度を定義します ハードウェア プロセッサが動作する いつでも。Windows ドライバー モデル (WDM) では、低い IRQL で実行されているコードは、高い IRQL で実行されているコードによって中断される可能性があります。実際、単一のマルチコア コンピューターでは、各 CPU が異なる IRQL に設定される場合があり、同期が複雑になります。
重要なルールが 1 つあります。 CPU が PASSIVE_LEVEL を超える IRQL で実行されている場合、その CPU は、さらに高い IRQL でのアクティビティによってのみプリエンプトされます。これにより、ユーザー コード、カーネル関数、遅延呼び出し元 (DPC)、およびデバイス割り込みサービス ルーチン (ISR) 間の共存が整理されます。
レベルと優先順位: PASSIVE_LEVEL、APC_LEVEL、DISPATCH_LEVEL、DIRQL
一般的に、 x86では0から31までのIRQL値が使用され、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などです。この設計により、これらのうちの1つが内部キューやその他の共有リソースにアクセスしている間、同じレベルの別のルーチンがそのCPU上でそのルーチンをプリエンプトすることがなくなります。これは、プリエンプションルールにより、上位レベルの割り込みのみが許可されるためです。
DISPATCH_LEVELとプロファイリング/高レベルの間には、 各デバイスのハードウェア割り込み(DIRQL)デバイスのIRQLは、他のデバイスに対するデバイスの優先順位を定義します。WDMドライバーは、IRP_MN_START_DEVICEを指定したIRP_MJ_PNP中にこのIRQLを取得します。このデバイス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
これらの問題に関連する2つの典型的なバグチェックは IRQL_NOT_LESS_OR_EQUAL (0xA) y ドライバー_IRQL_NOT_LESS_OR_EQUAL (0xD1)どちらも、ページング可能な(または無効な)アドレスに、IRQL が高すぎる状態でアクセスしようとしたことを示します。これは通常、ドライバが誤ったアドレスを使用している、不正なポインタを参照している、またはページング可能なコードを不適切なレベルで実行していることが原因です。
特定の場合 ドライバー_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
障害が発生した CPU の状況を把握できます。
たくさん コマンド 山積みの 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 が自分に合わない場合は、 基本的な対策を適用するイベントビューアのシステムログで特定のデバイス/ドライバに関するエラーがないか確認し、ブルースクリーンで表示されたドライバを更新または無効化し、Windowsのバージョンとハードウェアの互換性を確認し、RAMに問題があると思われる場合はWindowsメモリ診断を使用してください。これらの対策は簡単ですが、 彼らは多数の事件を解決する.
実例:BSODがランダムに見える場合
Windows 10 Pro(AMD Ryzen 5 3400G CPU、 GPU NVIDIA GeForce GTX 1660 Ti と Gigabyte B450 AORUS PRO WIFI ボード(RAM 16GB)で断続的に「IRQL_LESS_OR_NOT_EQUAL」画面が表示されるようになりました。必須ドライバー(ネットワーク、グラフィック)は既に更新済みで、Windows Updateもすべてインストール済み、メモリツールも実行済みですが、問題は検出されませんでした。
このようなシナリオでは、 次のステップはWinDbgでダンプを分析することです パターンを探します:落下時に関係するプロセス(例えば、 explorer.exe
)、グラフィカルインターフェースモジュール(win32kfull.sys
)などの機能 xxxProcessNotifyWinEvent
スタックに現れる。このモジュールはWindowsであるが、トリガーとなるのは多くの場合、不適切なIRQLでメモリを使用するサードパーティ製ドライバ(グラフィックス、入力、オーバーレイ、キャプチャカード)であり、その内部で障害が発生する。 win32k
.
ここでの実際的な推奨事項は オーバーレイソフトウェアを一時的に無効にする (キャプチャ、GPU OSD)、マクロ付きのマウス/キーボードなどのアグレッシブなソフトウェア周辺機器ドライバー、そしてベータ版のグラフィックスドライバーなど、様々なドライバーをテストし、問題を絞り込みます。疑わしいドライバーに対してDriver Verifierを使用すると、より明確なスタック情報が得られ、問題を絞り込むのに役立ちます。
非常に一般的なネットワークパターン:ndis.sysが必ずしも原因ではない
もう一つの典型的なケース: ndis.sysのスクリーンショット (Windowsネットワーク層)。実際のコンピュータでは、起動するとすぐにシステムがクラッシュします。現実的な解決策は、 セーフモード ネットワーク機能がない場合、 デバイスマネージャ 問題を切り分けるために、「ネットワーク アダプター」の下のアダプターを無効にします。
そのチームには Realtek PCIe GBE ファミリー コントローラと 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以上で実行中は、ページング可能な関数を呼び出さないでください。これには、ページングされたセクション内のデータへの参照を避け、DDKに記載されているカーネルヘルパーのIRQL制限を尊重することが含まれます。
共有データを同期するには、 「常に同じ高い IRQL で共有データにアクセスする」というルールを適用する 必要に応じてスピンロックを使用してください。マルチプロセッサでは、IRQLだけでは異なるCPU間の排他性は保証されません。スピンロックは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
オーバーレイとGUIインタラクションドライバを確認してください。多くの場合、問題は そのルートで出現するのは第三者によって破壊された記憶である.
IRQLを確認することを忘れないでください !irql
、そして対比: DISPATCH_LEVEL(2)でパラメータ3が読み取り/書き込み/実行を示している場合 ページ区切り可能なページの場合、なぜ落ちたのかの手がかりはすでにあります。その手がかりを ln
特定の関数を取得するには、パラメータ 4 を使用します。
理解します IRQL とは何ですか? カーネル実行にどのように組み込まれるかは、ノイズとシグナルを区別するのに役立ちます。ユーザーの場合は、 ドライバーとハードウェア (Verifier、イベント、テストはデフォルトで有効です)。開発を行う場合は、IRQL、非ページメモリ、スピンロックによる同期に関するルールを厳守してください。適切なツール(WinDbg、Verifier)を使用し、パラメータ(1、3、4)を注意深く読み取ることで、 これらのバグチェックはもはや謎ではありません。 そしてそれらは体系的に対処できる問題になります。
バイトの世界とテクノロジー全般についての情熱的なライター。私は執筆を通じて自分の知識を共有するのが大好きです。このブログでは、ガジェット、ソフトウェア、ハードウェア、技術トレンドなどについて最も興味深いことをすべて紹介します。私の目標は、シンプルで楽しい方法でデジタル世界をナビゲートできるよう支援することです。