Linuxで割り込みを処理する方法は?

Linuxで割り込みを処理する方法は?

私が知っているすべては、それがプロセッサピンであるInterruptことだけです。hardware signal assertionしかし、Linuxオペレーティングシステムがこれをどのように処理するかを知りたいです。
中断が発生した場合はどうなりますか?

答え1

これは、低レベルの処理のための高レベルのビューです。私は単純で一般的なアーキテクチャを説明しています。実際のアーキテクチャはより複雑であるか、いくつかの点で異なる場合がありますが、この程度の詳細レベルでは問題にはなりません。

いつ邪魔するこれが発生すると、プロセッサは割り込みがマスクされていることを確認します。もしそうなら、マスクが剥がれるまでは何も起こりません。割り込みがマスクされていない場合、プロセッサは保留中の割り込みがある場合は1つを選択します。

その後、プロセッサはメモリの特定のアドレスに分岐して割り込みを実行します。そのアドレスのコードは次のとおりです。割り込みハンドラ。プロセッサがそこから分岐すると、割り込みをマスクし(割り込みハンドラが排他制御を持つ)、いくつかのレジスタの内容をどこか(通常は他のレジスタ)に格納します。

割り込みハンドラは通常、データを送受信するために割り込みをトリガした周辺機器と通信して実行する必要があるタスクを実行します。タイマーによって割り込みが発生すると、ハンドラはオペレーティングシステムスケジューラを起動して他のスレッドに切り替えることができます。ハンドラは、実行が完了すると、保存されたレジスタを復元し、割り込みマスクを解放する特別な割り込み戻りコマンドを実行します。

割り込みハンドラは他の割り込みが実行されるのを防ぎ、すばやく実行する必要があります。 Linuxカーネルでは、割り込み処理は2つの部分に分けられます。

  • 「上半分」は割り込みハンドラです。これは通常、ハードウェアと通信し、カーネルメモリのどこかにフラグを設定するなど、必要な最小限の作業を実行します。
  • 「サブハーフ」は、プロセスメモリへのデータのコピー、カーネルデータ構造の更新などの他の必要な処理を実行する。割り込みが有効な状態で実行されているため、時間がかかる可能性があり、システムの他の部分を待つのが中断される可能性があります。

いつものように、このトピックの詳細については、以下をお読みください。Linuxデバイスドライバ;第10章中断についてです。

答え2

ザイルズは説明する一般的な割り込みに関しては、以下は特にIntelアーキテクチャベースのLinux 2.6に適用されます(一部はIntel仕様に基づいています)。

割り込みは、プロセッサが命令を実行する順序を変更するイベントです。
割り込みには2種類あります。

  • 同期中断(例外)命令の処理時にCPUによって生成される
  • 非同期割り込み(割り込み)他のハードウェアデバイスから発行

プログラミングエラーのため例外が発生しました(fe除算エラーページエラー過剰)はカーネルによって処理されなければなりません。彼はプログラムに信号を送り、エラー回復を試みます。

次の 2 つの例外が分類されます。

  • プロセッサで例外が検出されました。異常な状況が検出されると、CPUによって生成されます。間違って一般的に校正が可能で、履行報告、やめるすべての深刻な間違い。
  • プログラムされた例外プログラマが要求し、トラップのように処理されます。

割り込みは、I / Oデバイス(キーボード、ネットワークアダプタなど)、インターバルタイマー、および(マルチプロセッサシステムの場合)他のCPUで発生する可能性があります。割り込みが発生すると、CPUは現在の命令を停止し、新しく到着した割り込みを実行する必要があります。彼は割り込みを処理した後(おそらく)復元するために、以前に中断されたプロセス状態を保存する必要があります。

割り込み処理は機密作業です。

  • 割り込みはいつでも発生する可能性があり、カーネルはできるだけ早く割り込みを削除しようとします。
  • 割り込みは他の割り込みによって中断される可能性があります。
  • カーネルには絶対に中断できない領域があります。

2 つの異なる割り込みレベルが定義されます。

  • マスク可能割り込みI / Oデバイスから放出され、シールドまたは非シールドの2つの状態にすることができます。マスクされていない割り込みのみ処理されます。
  • 遮蔽不可能割り込み;重要なエラー(ハードウェアエラーなど)は常にCPUによって処理されます。

各ハードウェアデバイスには固有の割り込み要求(IRQ)ラインがあります。 IRQは0から番号が付けられます。すべてのIRQラインはPIC(Programmable Interrupt Controller)に接続されています。 PICはIRQを受け取り、それをCPUに割り当てます。特定のIRQラインを無効にすることも可能です。
最新のマルチ処理Linuxシステムには、IRQ要求をCPU間で均等に配布する最新のAPIC(Advanced PIC)が含まれることがよくあります。

割り込みまたは例外とその処理との中間段階は割り込み記述子テーブル(IDT)です。このテーブルは、各割り込みまたは例外ベクトル(数値)を指定したハンドラ(fe除算エラー関数divide_error())によって処理されます。

IDTを介して、カーネルは発生する割り込みや例外を処理する方法を正確に知っています。


それでは、割り込みが発生した場合、カーネルは何をしますか?

  • CPUは各命令を実行した後(A)PICでIRQを確認します。
  • その場合は、IDTに問い合わせて、受信したベクトルを関数にマッピングしてください。
  • 承認されたソースによって割り込みが発生したことを確認してください。
  • 中断されたプロセスのレジスタを保存
  • 割り込みを処理するために対応する関数を呼び出します。
  • 中断されたプロセスの最近保存されたレジスタをロードして復元しようとします。

答え3

割り込み処理に関する最初の参加者は、周辺ハードウェアデバイス、割り込みコントローラ、CPU、オペレーティングシステムカーネル、ドライバです。周辺ハードウェアデバイスは割り込みの発生を担当します。オペレーティングシステムカーネルの注意が必要なときに割り込み要求ラインを主張します。これらの信号は、割り込み信号の収集を担当する割り込みコントローラによって多重化されます。また、割り込み信号がCPUに渡される順序を決定する役割も担います。割り込みコントローラには、特定の割り込み要求ライン(IRQL)を一時的に無効にして再度有効にする機能(IRQLマスキング)があります。割り込みコントローラは、収集された割り込み要求を順番にCPUに転送します。各命令が実行されると、CPUは割り込みコントローラから保留中の割り込み要求があることを確認します。 CPUが待機要求を検出し、内部CPU制御レジスタに割り込みイネーブルフラグがセットされると、CPUは割り込み処理を開始する。 LinuxカーネルはCPUの割り込みフラグを動作させ、割り込みコントローラと通信して割り込みの受け入れを制御するのを見ることができます。たとえば、Linuxは特定のデバイスの割り込み受け入れを無効にしたり、まったく無効にしたりできます。

プロセッサが割り込み要求を受け取った場合はどうなりますか?まず、CPU は割り込みフラグをリセットし、自動的に割り込みをディスエーブルします。割り込み処理が完了すると再び有効になります。同時に、CPUは、CPUをユーザーモードからカーネルモードに切り替えるために必要な最小限の操作を完了することで、中断されたコード実行を再開できます。 CPUは、制御が渡されるコードアドレスを見つけるためにLinuxカーネルによって埋められた特別なCPU制御構造を参照します。このアドレスは、Linuxカーネルの一部である割り込みハンドラの最初の命令アドレスです。

割り込み処理の最初のステップとして、カーネルは受信した割り込みベクトルを識別し、システムでどのようなイベントが発生したかを識別します。割り込みベクタは、Linuxがそれを処理するためにとるアクションを定義します。 2番目のステップでは、Linuxは中断されたプログラムで使用できる残りのCPUレジスタを保存します(CPUはそれを自動的に保存しません)。これは、Linuxが中断されたプログラムに対して透過的に割り込みを処理できるようにするため、非常に重要な作業です。第3段階では、Linuxはカーネル環境を設定し、必要なCPU状態を設定してカーネルモードへの移行を完了します。最後に、ベクタに関連する割り込みハンドラが呼び出されます。 (x86アーキテクチャ固有の例の詳細については、arch \ x 86 \ kernel \ entry_32.SのBUILD_INTERRUPT3マクロを参照してください。)周辺機器の場合、これはdo_IRQ()ルーチンです。 (アーチ\x86\kernel\irq.c参照)

ベクタ関連の割り込みハンドラは通常、 irq_enter() および irq_exit() を呼び出してラップされます。これらの関数ペアに含まれるコード領域は、他の領域に対してアトミックであり、cli / stiペアに対してもアトミックです。 irq_enter() および irq_exit() も、割り込み処理に関するいくつかの統計をキャプチャします。最後に、カーネルは受信した割り込みベクトルに割り当てられたirq番号を見つけるためにvector_irqテーブルを見て(arch \ x 86 \ kernel \ irq_32.cで)handler_irq()を呼び出します。

この時点で、Linuxでの割り込み処理の一般的な部分は終了します。カーネルは、デバイスドライバによってインストールされたデバイス固有の割り込み処理ルーチンをirq記述子の一部として見てそれを呼び出すためです。ドライバがこれらのハンドラをインストールしない場合、カーネルは割り込みコントローラの割り込みを受け入れ、通常の割り込みハンドラを終了します。

割り込み処理が完了すると、カーネルは以前に中断されたプログラムの状態を復元し、プログラムの実行を再開します。

関連情報