IRQL_NOT_LESS_OR_EQUAL とは何ですか?

IRQL_NOT_LESS_OR_EQUAL とは何ですか?

IRQL_NOT_LESS_OR_EQUAL とは何ですか? IRQL とは何ですか? IRQL を使用するものは何ですか? なぜ小さいか等しい必要があるのですか? 小さいか等しいでなくなる原因は何ですか? 小さいか等しいでなくなった状態から OS が回復できないのはなぜですか? IRQL は Windows にのみ影響しますか?

このエラーはかなり一般的私は助けを求めているのではなく、説明を求めているのです。

答え1

それは複雑です。 ;)

いや、本当にそうだよ。

IRQL は「割り込み要求レベル」の略です。これは、Windows x86 システムでは 0 から 31、x64 システムでは 0 から 15 の範囲の数値です。これは、カーネル モード タスクの他のカーネル モード タスクに対する相対的な「重要度」を表します。

IRQL は、プロセスやスレッドではなく、Windows が定義するプロセッサの状態です。プロセッサが実行している処理が他のタスクによって割り込まれる可能性があるかどうかを Windows に示します。新しいタスク (割り込みサービス ルーチンなど) の IRQL がプロセッサの現在の IRQL よりも高い場合は、現在のタスクを割り込むことができます。そうでない場合は割り込むことができません。マルチプロセッサ システムでは、各プロセッサに独自の IRQL があります。これには、ハイパースレッディングによって作成された「論理プロセッサ」が含まれます。

(「優先度」ではなく「重要度」という言葉を使用するのは、Windows の「優先度」はスレッドの優先度を指し、IRQL はそれとは異なるためです。スレッドの優先度とは異なり、同じ IRQL のカーネル タスクはタイム スライスされず、IRQL は自動ブーストとディケイの対象になりません。)

(ここでの「カーネル タスク」という用語は正式なものではないことにも言及しておきます。Windows では、これらのものを実際には「カーネル タスク」とは呼びません。これらは、プロセスやスレッドなどの管理対象オブジェクトではなく、x86 の「タスク ゲート」や「タスク マネージャー」に表示されるものとは何の関係もありません。私 (および他の人) がここで使用している用語では、「カーネル モード タスク」は実際には「IRQL 2 以上のカーネル モードで実行する必要がある、開始と終了が定義されているものすべて」を指します。割り込みサービス ルーチンは「カーネル モード タスク」の 1 つの例であり、DPC ルーチンも同様です。ただし、別の例としては、カーネル モード スレッドのコードがあります。このようなスレッドは IRQL 0 で開始しますが、コードの一部が上げるIRQL 2 以上に設定し、何かを実行してから以前の IRQL に戻る場合、コードの高 IRQL 部分は、ここで「カーネル タスク」と呼んでいるものの一例です。)

パフォーマンス モニターは、IRQL 2 で費やされた時間を「% DPC 時間」として、IRQL > 2 で費やされた時間を「% 割り込み時間」として表示します。これは、時間が実際に DPC ルーチンまたは ISR で費やされたか、または IRQL を低い値から上げた結果であるかに関係なく行われます。それぞれは、PerfMon が「% 特権時間」として表示するもののサブセットです。これは、「カーネル モード時間」というラベルが付けられるべきでした。

カーネルタスクがIRQL 2以上で開始されると、他のタスクよりも先に完了するまで実行されます。同じIRQL は同じプロセッサで開始されます。より高い IRQL のタスクによって中断される可能性があります (そのタスクがさらにより高い IRQL のタスクによって中断されるなど)。ただし、より高い IRQL のタスクが完了すると、制御は中断したタスクに戻ります。

IRQLは主にシリアル化メカニズムです。(多くの人は「同期」と言いますが、私はこの言葉を好みます。結果がより正確に表されるからです。) その目的は、特定の共有リソース (主に OS カーネル空間の共有データ構造) にアクセスする同じ CPU 上の複数のタスクが、それらの構造を破壊するような方法で互いに割り込むことができないようにすることです。

例えば、Windowsカーネル内の大量のデータ、特にメモリ管理データとスレッドスケジューラが使用するデータは、「シリアル化」IRQL 2 で実行する必要があります。つまり、そのようなデータを変更するタスクは、変更時に IRQL 2 で実行されている必要があります。より高い IRQL のタスクがそのようなデータを書き込もうとすると、同じデータに対する読み取り、変更、書き込みサイクルの途中にある IRQL 2 タスクを中断する可能性があるため、破損が発生する可能性があります。したがって、より高い IRQL のタスクは、そのような操作を実行できません。

より高い IRQL のタスクは、主にデバイス ドライバーの割り込みサービス ルーチンです。これは、すべてのデバイスの割り込みが IRQL > 2 で発生するためです。これには、OS で時間管理と時間駆動アクティビティを駆動するマザーボード上のタイマー チップからの割り込みが含まれます。その IRQL は、すべての「通常の」ハードウェア デバイスの IRQL よりも高くなります。

IRQL 2 以上は、ハードウェア割り込みによってトリガーされないカーネル タスクに使用されますが、通常のスレッド スケジューリング (待機を含む) は実行できません。したがって、プロセッサが IRQL 2 以上になると、IRQL が 2 未満に下がるまで、そのプロセッサではスレッド コンテキストの切り替えは実行されません。

ユーザー モード コードは常に IRQL 0 です。カーネル モード コードは、0 から最大値までの任意の IRQL で実行できます。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 以下ではない値は必ずしも 1 ではありませんが、発生することはまれです。WinDBG ドキュメントにそれらがリストされています。

関連情報