web-dev-qa-db-ja.com

正確にはIRQL_NOT_LESS_OR_EQUALとは何ですか?

正確にはIRQL_NOT_LESS_OR_EQUALとは何ですか? IRQLとは何ですか? IRQLを使用するものは何ですか?なぜそれ以下にする必要があるのですか?それが以下にならないのはなぜですか? OSが回復しないのはなぜですか? IRQLはWindowsにのみ影響しますか?

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

16
Aaron Franke

それは複雑です。 ;)

いいえ、本当にそうです。

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から始まりますが、コードの一部の場合raisesをIRQL 2以上にして、何かを実行してから、以前のIRQLに戻ります。コードのIRQLの高い部分は、ここで「カーネルタスク」と呼んでいるものの一例です。

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

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

IRQLは主にシリアライズメカニズムです。 (多くの場合、「同期」と言いますが、結果をより正確に説明しているので、このWordを好みます。)その目的は、特定の共有リソースにアクセスする同じCPU上の複数のタスク(主にOSカーネルスペースの共有データ構造)を保証するのに役立つことです。それらの構造を破壊する可能性のある方法でお互いに割り込むことは許可されていません。

たとえば、Windowsカーネルの大量のデータ、特にメモリ管理データとスレッドスケジューラが使用するデータは、IRQL 2では"serialized"です。これは、このようなデータを変更する場合は、IRQL 2で実行する必要があります。上位のIRQLタスクがそのようなデータを書き込もうとすると、同じデータの読み取り-変更-書き込みサイクルの途中にあるIRQL 2タスクが中断された可能性があるため、破損を引き起こす可能性があります。したがって、IRQLの高いタスクでは、それを行うことはできません。

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

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

ユーザーモードコードは常にIRQL 0です。カーネルモードコードは、0から最大値までの任意のIRQLで実行できます。 IRQL 1は特殊なケースです。これはカーネルモードのみですが、スケジューリングには影響せず、実際にはプロセッサよりもスレッドの状態です。たとえば、スレッドコンテキストの切り替え中に保存および復元されます。

さまざまなシリアル化の保証を維持するために、ほとんどの例外(ゼロによる除算、またはページフォールトのようなメモリアクセス違反など)は、IRQL 2以上では単純に処理できません。 (IRQL 2 btwは一般に「ディスパッチレベル」または「DPCレベル」と呼ばれます。)

そして今、私たちはついにこのバグチェックコードを説明することができます!

IRQL_NOT_LESS_OR_EQUALの最も一般的なケースは、ページフォールト(「常駐していない」仮想アドレスへのアクセスの試み)、またはメモリアクセス違反(読み取り専用ページへの書き込み、または定義されていないページへのアクセスの試み)が原因です。まったく)、それはIRQL 2以上で発生します。

このような例外がIRQL 0または1で発生した場合、それらはシステム提供のコード(ページフォールトハンドラーなど)または開発者が提供した例外ハンドラーのいずれかによって「処理」できます。ただし、IRQL 2以上で発生した例外はほとんど処理できません。

つまり、バグチェックコードは、「IRQLが2以上のときに、IRQL 0または1でのみ処理できる型の例外が発生した」ことを意味します。つまり、「1以上」です。奇妙な言い回しですが、あります。

このバグチェックをトリガーできるものは他にもいくつかあり、IRQLが1以下ではない値は常に1ではありませんが、まれにしか発生しません。 WinDBGのドキュメントにそれらがリストされています。

28
Jamie Hanrahan