3、中断控制器(PIC/APIC):8259A可编程中断控制器、高级可编程中断控制器(APIC)、中断向量表

好,咱们今天聊聊中断控制器。这东西,说白了就是CPU的“秘书”。CPU很忙,不能谁来了都亲自接待。中断控制器负责收集中断请求,排好优先级,再挑一个最重要的告诉CPU。

我个人习惯把中断控制器分成两个时代:老派的8259A,和新派的APIC。你想想看,早期的PC只有一根中断线,所有设备都得挤在这根线上。后来多核CPU出现了,老办法就不灵了。嗯,咱们一个一个来看。

3.1 8259A可编程中断控制器

8259A是Intel在80年代推出的经典芯片。我记得刚入行时,还在老式工控板上见过它。它支持8个中断源,但可以通过级联扩展到64个。

它的核心工作流程是这样的:

  • 中断请求:外设通过IRQ引脚发送请求。
  • 中断判优:8259A根据优先级决定谁先上。
  • 中断响应:CPU发回INTA信号,8259A把中断向量号送上数据总线。

这里有个关键点——中断向量号。8259A需要提前初始化,告诉它每个IRQ对应哪个向量号。比如IRQ0通常对应向量号0x08(时钟中断)。

初始化代码示例(伪代码):

// 初始化8259A主片
mov al, 0x11        // ICW1: 边沿触发,级联模式
out 0x20, al
mov al, 0x08        // ICW2: 中断向量基址 = 0x08
out 0x21, al
mov al, 0x04        // ICW3: 从片连接在IRQ2
out 0x21, al
mov al, 0x01        // ICW4: 8086模式,自动EOI
out 0x21, al

我曾经在一个老项目中调试8259A,发现中断响应总是不对。查了半天,原来是ICW2的基址设错了,导致中断向量号跟中断服务程序对不上。这种坑,你只要踩过一次就忘不了。

避坑指南:我曾经在级联配置时忘记设置ICW3,结果从片的中断永远无法触发。记住,主片和从片的ICW3必须严格对应。

3.2 高级可编程中断控制器(APIC)

到了多核时代,8259A就不够用了。为什么?因为它只能把中断发给一个CPU。APIC的出现解决了这个问题。

APIC分为两部分:

  • 本地APIC(LAPIC):每个CPU核心都有一个,负责处理本地中断。
  • I/O APIC:负责收集外设的中断,再分发到各个LAPIC。

APIC支持三种中断模式:

模式 说明 应用场景
固定模式 中断固定发给某个CPU 特定设备绑定核心
最低优先级模式 发给当前最空闲的CPU 负载均衡
轮询模式 按顺序轮流分配 简单分发

我个人觉得,最低优先级模式最实用。它能让中断处理负载均匀分布到各个核心上。但要注意,如果配置不当,可能导致中断“乒乓”效应——中断在两个核心之间来回跳,反而降低性能。

小技巧:在Linux中,你可以通过/proc/irq/目录查看每个中断的亲和性设置。我习惯把网络中断绑定到某个特定核心,避免缓存抖动。

3.3 中断向量表

中断向量表,说白了就是一张“地址映射表”。每个中断向量号对应一个中断服务程序的入口地址。

在实模式下,中断向量表位于内存地址0x0000处,每个表项占4字节(段地址+偏移量)。保护模式下,它变成了中断描述符表(IDT),每个表项占8字节。

中断向量号的分配规则:

  • 0x00 - 0x1F:CPU异常和陷阱(比如除零错误、页错误)
  • 0x20 - 0x2F:8259A/APIC的硬件中断
  • 0x30 - 0xFF:用户自定义中断(比如系统调用)

IDT表项结构(保护模式):

struct IDTEntry {
    uint16_t offset_low;    // 中断处理函数低16位
    uint16_t selector;      // 代码段选择子
    uint8_t  ist;           // 中断栈表索引
    uint8_t  type_attr;     // 类型和属性
    uint16_t offset_high;   // 中断处理函数高16位
} __attribute__((packed));

嗯,这里要注意。中断向量表一旦设置错误,系统会直接崩溃。我曾经在写一个小型操作系统时,把IDT的基址寄存器设错了,结果一触发中断就三重故障重启。调试这种问题,只能用QEMU的日志功能一步步看。

警告:修改中断向量表时,务必关中断(CLI指令)。否则在修改过程中来了中断,CPU会读到不完整的表项,后果不可预测。

3.4 知识体系结构图

下面这张图,是我梳理的中断控制器知识体系。你可以看到,从8259A到APIC,再到中断向量表,它们是如何串联起来的。

中断控制器知识体系 8259A PIC APIC 中断向量表 8个中断源,可级联 边沿/电平触发模式 本地APIC + I/O APIC 多核中断分发 实模式:IVT 保护模式:IDT 核心:中断控制器负责收集、判优、分发 → CPU查向量表 → 执行ISR

这张图把三个核心概念串在了一起。你想想看,从8259A到APIC,本质上是中断分发能力的升级。而中断向量表,则是连接硬件中断和软件处理程序的桥梁。

我的经验:学习中断控制器,最好的办法是动手写一个简单的内核。你不需要实现全部功能,只要能初始化8259A或APIC,注册一个时钟中断处理函数,就能深刻理解整个流程。

好了,关于中断控制器的内容就这些。记住,无论是8259A还是APIC,它们的核心目标都一样:让CPU高效地处理外部事件。只是随着硬件的发展,实现方式越来越灵活、越来越强大。


可可精品资料库