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