4. x86 架构中断描述符表 (IDT):IDTR 寄存器、门描述符结构、中断门与陷阱门的区别

在 x86 架构中,中断描述符表 (IDT) 是将中断向量号映射到对应处理程序入口的核心数据结构。系统通过 IDTR 寄存器定位 IDT,每个表项称为一个门描述符,其中中断门与陷阱门是两种最常用的类型,它们在中断处理行为上存在关键差异。

4.1 IDTR 寄存器:IDT 的定位基址

IDTR 是一个 48 位的系统寄存器,存储 IDT 的线性基地址和表长度限制。CPU 在响应中断或异常时,通过 IDTR 中的基地址定位 IDT,并根据向量号索引对应的门描述符。

IDTR 寄存器结构:
  • 基地址 (32/64 位): IDT 在内存中的线性起始地址。
  • 表长度限制 (16 位): IDT 的字节大小减 1。最大支持 256 个门描述符,每个描述符 8 字节,因此限制值通常为 0x7FF (2047)。
IDTR 寄存器与 IDT 映射关系 IDTR 寄存器 (48 位) 基地址 (32/64 位) 表长度限制 (16 位) IDT (中断描述符表) — 最多 256 个门描述符

4.2 门描述符结构:8 字节的精确控制

每个门描述符占用 8 字节 (64 位),包含处理程序入口地址、段选择子、属性标志等关键字段。以下是 32 位保护模式下中断门/陷阱门的通用结构:

字节偏移 位域 字段名称 描述
0-1 0-15 Offset Low 处理程序入口地址的低 16 位
2-3 0-15 Segment Selector 目标代码段的段选择子
4 0-7 Reserved / Flags 保留位或标志位 (如 IST)
5 0-3 Gate Type 门类型:0xE = 中断门,0xF = 陷阱门
5 4 Zero (Storage) 必须为 0
5 5-6 DPL 描述符特权级 (0-3)
5 7 Present 段存在位 (1=有效)
6-7 0-15 Offset High 处理程序入口地址的高 16 位
关键字段说明:
  • Offset (32 位): 由低 16 位和高 16 位拼接而成,指向处理程序的第一条指令。
  • Segment Selector: 必须指向一个可执行的代码段描述符,且该段的 DPL 必须与门描述符的 DPL 匹配或更高。
  • DPL: 决定用户态 (Ring 3) 能否通过 INT 指令触发该中断门。异常处理通常设置为 0 (仅内核态)。

4.3 中断门与陷阱门的区别

中断门和陷阱门在结构上几乎相同,唯一的区别在于门类型字段 (中断门 = 0xE,陷阱门 = 0xF),但这一差异导致 CPU 在处理中断时对 IF 标志位 的行为不同:

特性 中断门 (Interrupt Gate) 陷阱门 (Trap Gate)
门类型值 0xE (1110b) 0xF (1111b)
IF 标志位处理 自动清除 IF,禁止嵌套中断 不修改 IF,允许嵌套中断
典型用途 硬件中断处理 (IRQ) 系统调用 (INT 0x80)、异常处理
嵌套中断风险 低 (自动屏蔽) 高 (需软件管理)
性能影响 略高 (需保存/恢复 IF) 略低 (无额外标志操作)
中断门 vs 陷阱门:IF 标志位行为对比 中断门 (Type=0xE) CPU 自动清除 IF → 关中断 执行处理程序 (不可嵌套) IRET 恢复 IF 陷阱门 (Type=0xF) CPU 不修改 IF → 中断保持原状态 执行处理程序 (可嵌套) IRET 恢复原 IF 状态
常见配置错误:
  • 门类型混淆: 将硬件中断配置为陷阱门,导致中断处理过程中 IF 未被清除,可能引发不可控的嵌套中断,造成栈溢出或数据竞争。
  • DPL 设置不当: 用户态可触发的门 (如系统调用) 若 DPL 设置为 0,则用户态 INT 指令会引发通用保护异常 (#GP)。
  • 段选择子无效: 门描述符中的段选择子必须指向一个存在的、可执行的代码段,否则 CPU 会触发段错误。

4.4 中断门与陷阱门的典型应用场景

  • 中断门: 用于外部硬件中断 (如定时器、键盘、磁盘)。自动关中断特性防止同一中断处理程序被自身或其他高优先级中断打断,保证处理原子性。
  • 陷阱门: 用于异常处理 (如缺页、除零) 和系统调用 (如 Linux 的 int 0x80)。异常处理通常需要保留中断状态,以便在修复异常条件后继续执行;系统调用则依赖用户态主动触发,无需硬件自动屏蔽中断。
初始化 IDT 的典型步骤:
  1. 在内存中分配 256 个门描述符 (共 2048 字节) 的数组。
  2. 为每个中断向量填充门描述符:设置段选择子 (内核代码段)、偏移地址 (处理函数)、门类型 (中断门/陷阱门)、DPL (通常为 0)、Present 位 (1)。
  3. 使用 LIDT 指令加载 IDTR 寄存器,指向 IDT 基地址和长度限制。
  4. 启用中断 (STI) 或等待异常触发。
; 示例:初始化 IDT 表项 (32 位保护模式)
; 假设 esi 指向门描述符,eax 包含处理函数地址,bx 包含段选择子
mov [esi], ax          ; Offset Low
mov [esi+2], bx        ; Segment Selector
mov byte [esi+4], 0    ; Reserved
mov byte [esi+5], 0x8E ; Present=1, DPL=0, Type=0xE (中断门)
shr eax, 16
mov [esi+6], ax        ; Offset High