IDT(中断描述符表)
在保护模式下,每个中断(前面提到了,包括外部中断,异常或软中断)都由一个向量来标识,Intel 称其为中断向量。而每个中断向量,都有一个8bits的向量号,8Bits表示一共有256个中断向量,与 256 个中断向量对应,IDT 中存有 256 个表项,表项称为门描述符(Gate Descriptor),每个描述符占 8 个字节。
中断到来之后,基于中断向量,IA-32硬件利用IDT与GDT这两张表寻找到对应的中断处理程序,并从当前程序跳转执行,下图显示的是基于中断向量寻找中断处理程序的流程:
IDT EXECUTABLE SEGMENT
+---------------+ +---------------+
| | OFFSET| |
|---------------| +------------------------->| ENTRY POINT |
| | | LDT OR GDT | |
|---------------| | +---------------+ | |
| | | | | | |
INTERRUPT |---------------| | |---------------| | |
ID----->| TRAP GATE OR |--+ | | | |
|INTERRUPT GATE |--+ |---------------| | |
|---------------| | | | | |
| | | |---------------| | |
|---------------| +-->| SEGMENT |-+ | |
| | | DESCRIPTOR | | | |
|---------------| |---------------| | | |
| | | | | | |
|---------------| |---------------| | | |
| | | | |BASE| |
+---------------+ |---------------| +--->+---------------+
| |
| |
| |
+---------------+
在开启外部硬件中断前,内核需对 IDT 完成初始化,其中IDT的基地址由IDTR
寄存器(中断描述符表寄存器)保存,可利用lidt
指令进行加载,其结构如下
INTERRUPT DESCRIPTOR TABLE
+------+-----+-----+------+
+---->| | | | |
| |- GATE FOR INTERRUPT #N -|
| | | | | |
| +------+-----+-----+------+
| * *
| * *
| * *
| +------+-----+-----+------+
| | | | | |
| |- GATE FOR INTERRUPT #2 -|
| | | | | |
| |------+-----+-----+------|
IDT REGISTER | | | | | |
| |- GATE FOR INTERRUPT #1 -|
15 0 | | | | | |
+---------------+ | |------+-----+-----+------|
| IDT LIMIT |----+ | | | | |
+----------------+---------------| |- GATE FOR INTERRUPT #0 -|
| IDT BASE |--------->| | | | |
+--------------------------------+ +------+-----+-----+------+
31 0
IDT中每个表项称为门描述符(Gate Descriptor),门描述符可以分为3种:
Task Gate,Intel设计用于任务切换,现代操作系统中一般不使用(可忽略)
Interrupt Gate,跳转执行该中断对应的处理程序时,
EFLAGS
中的IF
位会被硬件置为 0,即关中断,以避免嵌套中断的发生。Trap Gate,跳转执行该中断对应的处理程序时,
EFLAGS
中的IF
位不会置为 0,也就是说,不关中断。
门描述符的结构如下:
80386 TASK GATE
31 23 15 7 0
+-----------------+-----------------+---+---+---------+-----------------+
|#############(NOT USED)############| P |DPL|0 0 1 0 1|###(NOT USED)####|4
|-----------------------------------+---+---+---------+-----------------|
| SELECTOR |#############(NOT USED)############|0
+-----------------+-----------------+-----------------+-----------------+
80386 INTERRUPT GATE
31 23 15 7 0
+-----------------+-----------------+---+---+---------+-----+-----------+
| OFFSET 31..16 | P |DPL|0 1 1 1 0|0 0 0|(NOT USED) |4
|-----------------------------------+---+---+---------+-----+-----------|
| SELECTOR | OFFSET 15..0 |0
+-----------------+-----------------+-----------------+-----------------+
80386 TRAP GATE
31 23 15 7 0
+-----------------+-----------------+---+---+---------+-----+-----------+
| OFFSET 31..16 | P |DPL|0 1 1 1 1|0 0 0|(NOT USED) |4
|-----------------------------------+---+---+---------+-----+-----------|
| SELECTOR | OFFSET 15..0 |0
+-----------------+-----------------+-----------------+-----------------+
其中SELECTOR字段表示该中断对应的处理程序所在段的段描述符在GDT中的索引(想一想段寄存器里面是不是也有一个SELECTOR)。
若中断源为int
等指令产生的软中断,IA-32硬件处理该中断时还会比较产生该中断的程序的CPL与该中断对应的门描述符的DPL字段,若CPL数值上大于DPL,则会产生General Protect Fault,即#GP异常。
Last updated