异常和中断的基本概念
前四节里,PC 的值只有两个来源:自增(顺序执行)和转移指令写入(跳跃)。两者的共同点是——都由程序自己决定。
这一节引入第三个来源:PC 被硬件强行改写,而当前程序对此一无所知。
“强行”和”无所知”这两个词就是异常与中断的定义性特征,也是本节所有辨析的判据来源。跨到操作系统那边,OS 1.3.2 讲的是同一个机制的软件视角——两科讲同一件事,CO 讲硬件怎样把控制权夺走,OS 讲夺走之后怎么用。
机制
定义与两个判据
| 异常(内中断) | 中断(外中断) | |
|---|---|---|
| 来源 | CPU 内部——当前指令执行过程中 | CPU 外部——I/O 设备、定时器 |
| 与当前指令的关系 | 同步:同样的程序同样的输入,必然在同一条指令上发生 | 异步:与当前执行到哪条指令无关 |
| 典型 | 除零、缺页、地址越界、非法操作码、INT n | 键盘敲击、磁盘完成、时钟中断 |
| 能否屏蔽 | 一般不能(自陷类除外) | 可屏蔽中断可以,NMI 不行 |
| 检测时机 | 指令执行过程中发现 | 每条指令执行结束时统一检测 |
两个判据,一个足够定性、一个足够可操作:
判据一(定性):来源在 CPU 内还是外。
判据二(可操作):把程序重跑一遍,它还会在同一个地方发生吗? 会 → 异常(同步);不一定 → 中断(异步)。
判据二在做题时更好用,因为”内 / 外”有时会有争议(比如时钟中断的定时器可能在片内),而”重跑一遍是否可复现”从不含糊。
术语的混乱与统一
这一节的术语在不同教材、不同体系里不一致,必须先把口径统一。
| 说法体系 | ”中断”这个词指什么 |
|---|---|
| 广义(早期教材、408 常用) | 一切打断正常执行流的事件,内因外因都算。此时分”内中断 / 外中断” |
| 狭义(现代体系、Intel 手册) | 只指外部异步事件。内部同步事件叫”异常” |
408 两种口径都可能出现,判断方法是看题目有没有用”内中断 / 外中断”这对词:
- 出现”内中断” → 广义口径,此时内中断 = 异常
- 只说”异常和中断” → 狭义口径,二者并列
对照记忆表:
中断的定义性特征:硬件强行改写 PC
这一条是全节最需要焊死的判据,因为下面那个跨科的疑问、以及 5.5.2 的所有分类,全靠它。
一次中断响应里,硬件做了三件程序完全无法察觉的事:
- 在指令边界抢下控制权——当前指令刚执行完,下一条还没取
- 把 PC 和 PSW 存起来——为了将来能回来
- 把 PC 改成中断服务程序的入口地址
关键在于:这三件事没有任何一条指令参与。 程序里找不到一条 CALL 中断服务程序——它是中断隐指令,一段没有操作码、不在主存里、由硬件直接执行的动作。
反过来说,凡是”程序自己调用的”,都不是中断。 这条否定判据比正面定义更常用。
疑问点:
addEventListener那种注册回调的写法算中断吗?是操作系统在管,还是可以直接挂到中断服务程序上不算中断,而且用户态代码挂不到中断服务程序上。但这个联想的方向是对的——它们确实在同一条链上,只是隔了三层。
先用判据判一次:
addEventListener注册的回调,是被谁调用的?是被应用程序自己的事件循环调用的。浏览器、Qt、Java Swing 内部都有一个形如
while (true) { event = 取出下一个事件(); // 队列空则阻塞 分发给注册的回调(); }的循环。回调是这个循环主动调用的一个普通函数——控制权从来没有被夺走过。 按上面那条否定判据:“程序自己调用的,不是中断”。
但从按下一个键到回调被执行,链条上确实有一次真正的中断。完整的六层:
层 发生了什么 是不是中断 1 键盘控制器拉高 IRQ 线 —— 2 CPU 在指令边界响应,硬件改写 PC ✅ 这里,且只有这里 3 内核中断服务程序读扫描码,放进内核事件队列 内核态,ISR 内部 4 窗口系统(X11 / Wayland / Windows 消息队列)取走,投递给某个窗口 纯软件 5 应用的事件循环从队列里取出 纯软件 6 分发给 addEventListener注册的回调普通函数调用 “是操作系统在管吗”——是,第 3、4 层都是。 而且这正是分层的意义:硬件中断的处理必须极短(后面还有别的中断在等),所以 ISR 只做”把数据搬进队列”这一件事,真正的处理推迟到应用层慢慢做。这在 OS 里叫上半部 / 下半部的划分,OS 5.1.2 讨论 I/O 控制方式时是同一个思路。
“能不能直接挂到中断服务程序上”——用户态不能,理由是硬性的:
ISR 的运行环境 用户态回调 内核态(OS 1.3.1) 用户态 不能睡眠、不能缺页——它可能运行在关中断状态下 随便睡、随便缺页 用内核栈,栈空间很小 用户栈 地址必须在中断向量表里注册,只有内核能写 应用自己的数据结构 用户态能拿到的最接近中断的东西是「信号(signal)」——内核在返回用户态时强行改写用户程序的执行流去跑 signal handler。它确实是”被强行插入”的,所以常被称作”软件中断”,但它仍不是硬件中断:投递时机由内核选择,而且只在返回用户态那一刻。
把三种”异步”并排放一次,界限就清楚了:
机制 谁改写执行流 何时可能发生 运行在 硬件中断 硬件 任意指令边界 内核态 信号 内核 返回用户态那一刻 用户态 回调 / 事件循环 程序自己 事件循环取到事件时 用户态 越往下,“异步”越弱、可控性越强。
addEventListener在最底下一行——它看起来异步,是因为事件到达的时间不确定,而不是因为执行流被夺走。
中断请求的产生与传递
设备提出请求到 CPU 看见它,中间有三个环节:
| 环节 | 部件 | 说明 |
|---|---|---|
| 提出 | 设备的中断请求触发器 INTR | 设备就绪时置 1 |
| 允许 | 设备的中断屏蔽触发器 MASK | 被屏蔽的设备请求发不出去 |
| 汇总 | 排队器 / 中断控制器 | 多个请求同时到达时判优,见 5.5.3 |
CPU 侧还有一道总闸:PSW 中的中断允许位 IF(也写作 EINT)。
四个条件缺一不可,这个乘积式是判断”某中断能否被响应”这类题的完整依据。
为什么中断必须在指令边界响应
这是本章前几节埋下的伏笔在这里收口。
5.1.3 说过:切换只需保存 ISA 状态(GPRs、PC、PSW),IR、MAR、暂存器都不用保存。这个结论成立的前提,就是切换发生在指令边界——那一刻上一条指令已经完整做完、下一条还没开始,那些微体系结构寄存器里没有任何跨指令有用的信息。
如果允许在指令中间响应中断,就必须把暂存器 Y、Z、MAR、MDR、当前微指令的执行进度全部保存下来——而这些东西在不同的 CPU 实现里完全不同,程序就不再可移植了。ISA 与微体系结构的分层(4.1.1)会当场崩塌。
所以”指令边界响应”不是一个实现上的方便,而是 ISA 抽象能够成立的必要条件。 这一点在流水线里会变成”精确异常”这个更难的要求,见 5.6.3 和 5.5.3。
边界
边界辨析:异常 / 中断
- 异常:内部、同步、可复现——除零、缺页、非法指令、
INT n- 中断:外部、异步、不可复现——键盘、磁盘、时钟
可操作判据:重跑一遍,还会在同一条指令上发生吗?
边界辨析:广义中断 / 狭义中断
题目出现”内中断”这个词 → 广义口径,内中断 = 异常。 题目只说”异常和中断” → 狭义口径,二者并列。
不要在同一道题里混用两套口径。
层次辨析:硬件中断 / 信号 / 回调
三者都”异步”,但改写执行流的主体不同:
- 硬件中断:硬件改 PC,任意指令边界
- 信号:内核改用户执行流,返回用户态时
- 回调:程序自己的事件循环调用,完全同步
只有第一种是本章讲的中断。
边界辨析:系统调用是异常还是中断
对照速查
| 事件 | 类型 | 同步/异步 |
|---|---|---|
| 除数为 0 | 异常(故障) | 同步 |
| 缺页 | 异常(故障) | 同步 |
| 访问越界 | 异常(故障或终止) | 同步 |
| 非法操作码 | 异常(故障) | 同步 |
INT 0x80 / syscall | 异常(自陷) | 同步 |
断点调试 INT 3 | 异常(自陷) | 同步 |
| 键盘按键 | 中断 | 异步 |
| 磁盘传输完成 | 中断 | 异步 |
| 时钟中断 | 中断 | 异步 |
| 电源故障 | 中断(NMI) | 异步 |
| Cache 未命中 | 都不是 | 硬件自行处理,程序不可见 |
最后一行值得单独看:Cache 缺失由硬件完全处理完,不改写 PC、不进入任何服务程序,所以它既不是异常也不是中断。而缺页是异常——因为它需要操作系统介入去读磁盘。判据仍是那一条:PC 有没有被强行改写。 两者的完整对比见 3.6.5。
考点
- 异常与中断的分辨:给一个事件问类型。用”内/外 + 同步/异步”两条判据。
- 系统调用属于哪一类:答异常中的自陷,不是中断。
- 响应的四个条件:设备请求、未被屏蔽、CPU 开中断、一条指令执行结束。
- Cache 缺失不是异常:高频陷阱,判据是”是否改写 PC 进入服务程序”。
- 为什么在指令边界响应:答保证保存的状态是完整的 ISA 状态,微体系结构状态无需保存。
链接
- 🏠 返回总览:计算机组成原理第 5 章:中央处理器总览
- ⬅️ 上一节:5.4.3 微程序控制器
- ➡️ 下一节:5.5.2 异常和中断的分类
- 🔗 OS 视角:OS 1.3.2 中断和异常
- 🔗 系统调用:OS 1.3.3 系统调用
- 🔗 缺页 vs Cache 缺失:3.6.5 虚拟存储器与 Cache 的比较
- 📖 名词库:第 5 章名词库