本节摘要:处理器只有一根可屏蔽中断引脚,8259 用一根引脚管起八级申请、可级联到六十四级;理解它的编程模型,就同时理解了 ARM GIC 乃至消息式中断的全部现代变体——权力结构从未改变。
前两站把单次中断的旅程走完了,本站看旅程背后的管理机构。外设成打、引脚一根,这中间必须有中间层——中断控制器。它是中断系统的"接线员兼调度台",也是本章主线里那个替所有外设举手、送类型码的角色。
8259 的职能有四项,全部围绕"把多路申请整理成一路受控输出":接收与登记八个申请引脚上的请求,正在服务的挂"在服务"牌,后来的按优先级排队;屏蔽管理,屏蔽寄存器 IMR 让软件按位关闭某个申请源,与 IF 的全局开关不同,这是分路闸刀;优先级仲裁,多路同时申请时挑出最高者;供类型码,CPU 应答时把选中源的中断类型码放上数据总线。四项职能合起来,处理器只需保持一根 INTR 引脚,就能接待一整层楼的外设。
编程模型是两套命令字。初始化命令字 ICW 在开机时按固定次序写入,为控制器定基调:
; 8259 初始化要点(主片,示意) MOV AL, 00010001B ; ICW1 边沿触发 级联 要 ICW4 OUT 20H, AL MOV AL, 08H ; ICW2 起始类型码:八级占 08H 到 0FH OUT 21H, AL MOV AL, 00000100B ; ICW3 主片IR2接从片 OUT 21H, AL MOV AL, 00000001B ; ICW4 8086模式 非自动结束 OUT 21H, AL ; 运行期的操作命令字 MOV AL, 11101111B ; OCW1 屏蔽 IR4(按位置1即屏蔽) OUT 21H, AL
这段代码里有三个高频考点,也都是高频事故点。ICW2 定类型码基址,写错一位,所有外设的向量整体错位——服务程序全被跳错门;OCW1 按"置一屏蔽"约定,把位语义记反就会把想开的关掉;非自动结束模式下,服务程序结尾必须发结束命令 OCW2,漏发则同级与更低级的申请永远被"在服务"牌挡住。级联时主片的某个引脚接从片的输出,从片的八级通过它升级上楼,一套 ICW3 在两边各自说明接线——这就是"一根引脚管六十四级"的来路。
ARM 世界的通用中断控制器 GIC 换了名字与总线,没换权力结构:申请源分级管理(处理器私有的本地中断、共享外设中断、核间通信的软件中断),优先级寄存器对应 IMR 与仲裁逻辑,转发与应答寄存器对应 8259 的应答与结束命令——对照着看,每个寄存器都能找到祖辈的影子。
真正结构性的变化是消息式中断。PCIe 时代设备不再拉申请线,而是向指定内存地址写一笔带编号的数据,"举手中断"变成"寄快递中断":申请线数量的物理限制消失了,中断与数据可以打包送达,多核路由也变成了消息寻址问题。代价是消息必须先穿过总线与内存系统——4.3 节的仲裁秩序又一次成为中断机制的地基。观察这个演化轨迹,你会发现接口技术的守恒律:机制会搬家,职责清单不会——登记、屏蔽、仲裁、供码、销号,五件事永远有人在办。
把两套命令字的全貌列齐,编程时按表点菜:
| 命令字 | 何时写 | 管什么 |
|---|---|---|
| ICW1 | 初始化第一步 | 触发方式(电平或边沿)、是否级联 |
| ICW2 | 紧随 ICW1 | 类型码基址,八级各占一号 |
| ICW3 | 级联时 | 主从接线说明,两边都要写 |
| ICW4 | 初始化收尾 | 处理器模式、自动结束与否、缓冲方式 |
| OCW1 | 运行期随时 | 屏蔽寄存器,按位开闸合闸 |
| OCW2 | 服务程序结尾 | 结束命令、优先级方式调整 |
| OCW3 | 运行期 | 特殊屏蔽、读寄存器等杂务 |
优先级的花样比想象的多。默认是固定优先级:IR0 最大、IR7 最小,简单但会让低级别饿肚子。优先级轮转在每次服务结束后把刚服务过的降为最低,轮着坐庄——适合各申请源地位平等的场景。优先级指定则允许软件随时指定某一级为最低,从而把任何一级抬成最高,为动态调整留了后门。这些方式都通过 OCW2 的编码切换——一颗八一级的芯片,把调度理论的入门题全部内置了。
初始化还有一个隐蔽坑:级联系统的从片也要完整跑一遍 ICW 流程,且主片的 ICW3 写"哪个引脚挂了从片"、从片的 ICW3 写"挂在主片哪个引脚"——两边必须互为镜像。镜像写反的症状很典型:从片的申请能触发主片,但类型码送错,服务程序全被跳错门。排查时先把两片 ICW3 的值并排抄出来对一遍,十分钟的事。
级联的服务流程也值得走一遍。从片的某级申请到来:从片先内部登记仲裁,胜出后通过主片的级联引脚代为举手;主片应答时,从片把类型码放上数据总线,CPU 据此跳转;服务结束时,结束命令要分别送到从片与主片——两级都要销号。两片级联、十五级申请,流程多了一跳,销号多了一步;八片级联到六十四级的系统里,"谁家的申请、谁家销号"就成了必须表格化的纪律。级联教会的是一件更大的事:机制可以叠层,但每一层的簿记都不能省。
问:自动结束模式(AEOI)不是更省事吗,为什么默认不用? 它在中断响应时就自动清"在服务"牌,省去服务程序结尾的销号命令。但省事有代价:若服务程序还没跑完同级申请又来(嵌套或重入),控制器已经不设防了。确定性优先的系统宁可手动销号——把"办完"的定义权握在自己手里。
问:现代处理器中断管理那么复杂,核心改变是什么? 规模与拓扑:几十个核、几百个申请源、核间通信都要管理,所以控制器变成分布式的多级结构,路由策略成了新课题。但逐层剥开,每一级做的仍是登记、屏蔽、仲裁、供码、销号五件事——学 8259 就是在学 GIC 的骨架。
机制的、管理的都讲完了——下一站进入实战:一次真实的中断丢失,从现象到元凶的完整排查。