Linux の割り込み処理 【第1回】
本日は 「Linux の割り込み処理 【第1回】」 ということで書きたいと思います。
以下の内容は Intel 8086 系です。他のアーキは別の機会ということで。
「割り込み」 と一口に言っても、IRQ を介したハード割り込みや、CPU が発生させる例外など、色々あります。
各割り込みには 0 から 255 までの番号が付けられており、それぞれを 「割り込みベクタ」 と呼んでいます。
それらのベクタは idt_table (Interrupt Descriptor Table) というものに書かれており、ベクタの種類や割り込みに対する処理などを知ることができます。
crash> rd idt_table 512
c03cc000: 00605250 c02d8f00 006052e0 c02d8e00
c03cc010: 00605330 c02d8e00 006053c8 c02dee00
c03cc020: 006053f8 c02def00 00605404 c02def00
c03cc030: 00605410 c02d8f00 006052a8 c02d8f00
(中略)
c03cc7e0: 00605170 c02d8e00 00605190 c02d8e00
c03cc7f0: 006051f0 c02d8e00 00605210 c02d8e00
ベクタはサイズが 8 byte で 256 個ありますので、合計 2048 byte です。
そして、各割り込みの使用目的は以下のようになっています。
- 0 から 31 までのベクタは例外と non maskable 割り込み
- 32 から 47 までのベクタは IRQ による割り込み
- 48 から 255 までのベクタはソフトウェア割り込み
例として、0 番について見ます。
crash> rd idt_table 2
c03cc000: 00605250 c02d8f00
40 - 43 bit がこのベクタの種類を表しており、
- 0101 ならタスクゲート (最後が 500)
- 1110 なら割り込みゲート (最後が e00)
- 1111 ならトラップゲート (最後が f00)
となります。これはトラップゲートです。
次にベクタが呼ばれた場合の処理ですが、0 - 15 bit が low-part, 48 - 63 bit が high-part となる 32 bit のアドレスが使用されます。
この場合、アドレスは 0xc02d5250 となります。
これは以下のように、除算エラーの例外ハンドラです。
crash> sym c02d5250
c02d5250 (T) divide_error
次に、14 番について見ます。
crash> rd idt_table+14*8 2
c03cc070: 00605464 c02d8e00
40 - 43 bit が e00 なので、割り込みゲートです。
0 - 15 bit を low-part, 48 - 63 bit を high-part として組み合わせると、アドレスは 0xc02d5464 となります。
これは以下のように、ページフォールトの例外ハンドラです。
crash> sym c02d5464
c02d5464 (T) page_fault
今回はここまでにしますが、次回 (があれば) IRQ の割り込みや、システムコールについて書きたいと思います。



コメント