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到APIC,本质上是中断分发能力的升级。而中断向量表,则是连接硬件中断和软件处理程序的桥梁。
我的经验:学习中断控制器,最好的办法是动手写一个简单的内核。你不需要实现全部功能,只要能初始化8259A或APIC,注册一个时钟中断处理函数,就能深刻理解整个流程。
好了,关于中断控制器的内容就这些。记住,无论是8259A还是APIC,它们的核心目标都一样:让CPU高效地处理外部事件。只是随着硬件的发展,实现方式越来越灵活、越来越强大。
可可精品资料库