Appearance
中断和异常的处理
2026 大纲 一(三)2 中断和异常的处理。
用户程序拿走了 CPU,OS 怎么把它要回来
上一节说清了 OS 的权威来自硬件给的模式位。但那里留下一个问题没答: OS 现在运行在用户态的程序手里,它怎么才能重新拿到 CPU?
它不能"主动去拿"——OS 自己也是代码,代码不执行就什么也做不了, 而此刻 CPU 正在执行用户程序。软件层面没有任何办法让一段不在运行的代码运行起来。 所以答案只能还是硬件:必须有一个机制,能在某些事件发生时强行打断当前指令流, 把 CPU 交给内核里一段指定的代码。 这个机制就是中断。
于是中断成了 OS 的驱动力,缺了它三件事都做不成:进不了内核态(用户程序拿到 CPU 就再也交不回来)、 无法抢占 CPU(一个死循环就锁死整机)、无法响应 I/O(只能轮询空耗)。 上一节讲的三条进内核的路——外中断、内中断、自愿性中断——其实是同一个机制的三种触发源。
这一节把这个机制拆开看:它怎么分类(按谁引发、按能不能恢复)、 一次中断从发生到返回都经过哪些步骤(哪些是硬件做的、哪些是 OS 做的)、 以及中断处理到一半又来一个中断怎么办。
一、中断的分类
内中断按"能不能恢复、返回到哪"再分三类:
| 类型 | 判据:这次异常是不是程序自己要的 / 能不能修复 | 处理方式 | 举例 |
|---|---|---|---|
| 陷入 Trap | 程序有意触发 | 处理后执行下一条指令 | 系统调用、断点 |
| 故障 Fault | 非本意,但可恢复 | 修复后重新执行引起故障的指令 | 缺页异常 |
| 终止 Abort | 非本意,且不可恢复 | 终止进程,无返回点可言 | 硬件故障、非法指令 |
中断技术的应用范围,以及另一套教材口径:按中断源分的五类中断事件(题干出现"程序性中断事件""自愿性中断事件"这类术语时展开)
中断的概念是怎么定型的。 中断技术最初仅作为设备向 CPU 报告 I/O 情况的手段,用来解决主机和设备的并行性问题;后来应用范围不断扩大,请求系统服务、实现并行工作、处理突发事件、满足实时要求都需要打断处理器的正常工作流程,中断的概念由此定型。
五类中断事件。 同一批事件,不同教材切法不同,两套说法都要认识。
| 中断事件 | 典型来源 | 处理原则 | 对应到内/外中断口径 |
|---|---|---|---|
| 硬件故障中断事件 | 电源故障、主存故障、总线奇偶校验错 | 保护现场、停机、向操作员报告,估计并恢复破坏 | 外中断中的不可屏蔽中断 |
| 程序性中断事件 | 除数为零/溢出、非法指令、用户态使用特权指令、地址越界、非法存取、虚拟地址异常 | 算术异常报告用户;非法指令/越界类终止进程;虚拟地址异常调整主存后重新执行指令 | 内中断中的 Fault / Abort |
| 自愿性中断事件(即系统调用) | 程序执行陷入指令 | 按功能号查系统调用入口表,执行服务例程,返回系统调用的下一条指令 | 内中断中的 Trap |
| I/O 中断事件 | 设备传输正常结束、故障、异常 | 正常结束则唤醒等待进程;故障则取状态字分析原因 | 外中断(可屏蔽) |
| 外部中断事件 | 时钟、间隔时钟(时间片到)、设备接入/结束、键鼠信号、关机重启 | 计时;时间片到则被中断进程让出处理器进就绪队列 | 外中断(可屏蔽) |
能对上的部分:自愿性中断事件就是 Trap;程序性中断事件覆盖了 Fault 与 Abort;I/O 中断事件 + 外部中断事件就是可屏蔽外中断;硬件故障中断事件对应不可屏蔽外中断。
分歧在哪:Trap/Fault/Abort 三分法是按返回位置切的(下一条 / 重新执行当前条 / 不返回),五分法是按中断源切的。所以"程序性中断事件"内部同时含可恢复的(虚拟地址异常 → 重新执行指令)与不可恢复的(非法指令 → 终止进程),它并不是 Fault 的同义词。两套分类不是同一维度的替代品,遇到题干用哪套术语就答哪套。
二、中断响应与处理流程
最简单的指令执行分为取指、解码、执行三步。中断能被发现,靠的是在这三步之后加入了一个"检查中断"的微操作:处理器完成一个执行周期后先看中断是否被允许,不允许就继续执行下一条指令;允许则检查是否有中断出现,有则触发相应硬件电路。这一步同时解释了两件事——外中断为什么在"一条指令执行完毕后"才被检测,以及关中断为什么能挡住中断。
发现并响应中断的硬件装置称为中断装置,按中断源分三套:中断控制器(响应处理器外的异步事件,含记录来源的中断寄存器与中断逻辑电路)、系统陷入机制(由陷入指令触发,引向系统调用处理程序)、指令陷入机制(由指令的控制逻辑与实现电路触发,引向异常处理程序)。
分界记法:硬件负责"把控制权准确地送到该去的地方"(断点 + 入口地址),软件负责"把事情办完再原样还回去"(现场 + 处理逻辑)。
换一个更好用的判据:凡是要动 PC、PSW 这两个特殊寄存器或模式位的,都是硬件做的—— 因为这些动作发生时 CPU 还在用户态,权限根本不够,只能靠硬件的自动机制完成。 剩下那些"用普通指令就能做的事"(保存通用寄存器、查表、调用函数)才轮到 OS。
断点与现场是两件事,分属两端,最容易搞反:断点指 PC 和 PSW,由硬件保存; 现场指通用寄存器,由软件保存。
时刻要分清:中断"发生时"和处理程序"执行时"不是同一状态
这是同一条流程上两个相邻却不同的时刻,混起来就会答反。
| 时刻 | 发生了什么 | CPU 处于哪一态 |
|---|---|---|
| ① | 用户进程正常运行 | 用户态 |
| ② | 中断/异常发生 | 通常仍是用户态——多数 I/O 中断、时钟中断、陷入、缺页都是在用户进程跑着的时候触发的 |
| ③ | 硬件响应:存断点、置模式位、取向量 | 正在切换 → 内核态 |
| ④ | 中断处理程序开始执行 | 必然是内核态 |
| ⑤ | 恢复现场,执行中断返回指令 | 切回原态(多为用户态) |
②和④的区别不在于"是不是内核态",而在于前者是触发切换的原因,后者是切换完成的结果。 说"中断发生时 CPU 处于内核态"是错的——如果它已经在内核态,那这次中断就不是从用户程序来的了。
哪些指令可能引起态切换
题目常给一条具体指令,问它执行时会不会导致用户态变内核态。判据有两条,沾上任意一条就"可能":
- 它本身是不是主动陷入指令(
trap/INT n/syscall)——是则必然切换; - 它执行过程中是否可能触发异常——算术指令可能除零溢出、访存指令可能缺页或越界,都算"可能"。
两条都不沾的才是"绝不切换",而这类指令只有一种:不访存、不可能出异常的纯寄存器运算, 比如寄存器取非、同寄存器间的加法。
注意外中断不在这个判据里:它与当前执行的是哪条指令无关,不算"由这条指令导致"。
三、中断向量与中断向量地址
| 术语 | 是什么 | 存在哪 |
|---|---|---|
| 中断向量 | 中断服务程序的入口地址(有的机器还含配套的 PSW) | 存放在中断向量表的表项里 |
| 中断向量地址 | 该中断向量在中断向量表中的存放地址,即表项自身的地址 | 由中断号(中断类型号)经硬件换算得到 |
完整链条:中断号 →(乘以表项长度加表基址)→ 中断向量地址 →(按此地址访存取出)→ 中断向量 → 送入 PC。说"中断向量地址就是中断服务程序入口"是错的,中间还差一次访存。
中断号 向量地址(表项) 表项内容 = 中断向量
0 → IVT+0×4 → 除零异常处理程序入口
1 → IVT+1×4 → 调试异常处理程序入口
...
14 → IVT+14×4 → 缺页异常处理程序入口
...
32+ → IVT+32×4 → 外设中断处理程序入口采用这种"表驱动"而不是"逐个判断中断源"的方式,好处是定位入口的时间与中断源数量无关——不管有多少种中断,都是一次乘加加一次访存。
四、多重中断(中断嵌套)
| 单重中断 | 多重中断(中断嵌套) | |
|---|---|---|
| 处理期间开不开中断 | 全程关中断 | 保护完现场后开中断 |
| 新到的高优先级中断 | 只能等当前处理完 | 立即打断当前中断处理程序 |
| 处理次序 | 严格按到达先后 | 先响应的可能被延后完成(后到的高优先级先做完) |
| 现场保存在哪 | 一层即可 | 依次压入核心栈,返回时逆序弹出 |
| 代价 | 高优先级事件响应慢,可能丢数据 | 栈开销与实现复杂度上升 |
为什么必须允许嵌套:处理一个慢速 I/O 中断可能耗时很久,若此期间发生电源故障这类紧迫事件却不能立即响应,后果不可挽回。为什么又要限制嵌套:每嵌套一层就要在核心栈上多压一层现场,工程上一般以不超过三重为宜;处理过程中通常不响应 I/O 中断这类紧迫度不高的事件,也不响应与正在处理的中断同类的事件。
控制"谁能打断谁"靠两样东西:
- 中断优先级:中断装置预设,原则是"以不发生中断丢失为前提"。一般由高到低为硬件故障中断 → 自愿性中断 → 程序性中断 → 外部中断 → I/O 中断,但各系统可不同(关机/重启中断在多用户系统里优先级最低,在个人计算机上却最高)。
- 中断屏蔽字:处理程序用软件设置,三个用途——① 系统程序执行期间延迟或禁止某些中断,以免共享数据结构被破坏;② 保证高优先级能打断低优先级、反之不能;③ 处理某级中断时屏蔽该级中断本身,防止同级相互干扰。最简单的实现是屏蔽与自己同级和比自己低的,放行比自己高的。
同一组事件在单重与多重下的两条时间线(想在时间轴上看清嵌套如何改变响应延迟与完成次序时展开)
设 I/O 中断处理程序需运行 100 μs,硬件故障中断处理程序需运行 20 μs,故障中断优先级更高。
单重中断。 判断能否被响应,第一件事永远是看当前中断是否开放,而不是看优先级——关中断的情况下优先级再高也进不来。单重系统全程关中断,
响应延迟
多重中断。 嵌套是否发生取决于两个条件同时满足:"中断已开放"且"新中断优先级高于当前屏蔽字放行的下限"。此处两条都满足 → 立即响应,响应延迟
:I/O 中断的现场被压入核心栈,转去处理故障中断 :故障中断处理完毕,逆序弹出现场,回到被打断的 I/O 中断处理程序继续 - I/O 中断还剩
要跑,于是在 结束
对照结论:嵌套只是把 CPU 时间"插队"给了高优先级中断,被打断者的剩余工作量一点没少,所以结束时刻整体后移了嵌套者的执行时间。多重中断把高优先级事件的响应延迟从 70 μs 压到 0,代价是 I/O 中断的完成时刻从 100 μs 推到 120 μs,并且改变了完成次序——先响应的反而后完成。
五、中断与进程切换的关系
中断处理结束时并不总是回到被中断的那个进程。中断返回前,OS 会检查是否需要重新调度:
| 情形 | 中断返回后 | 为什么 |
|---|---|---|
一次普通的系统调用(如 getpid) | 回到原进程原断点 | 没有任何进程状态发生变化 |
| 时钟中断且当前进程时间片用完 | 切换到另一进程 | 时间片到 ⇒ 被中断进程让出处理器进入就绪队列 ⇒ 触发调度 |
| I/O 完成中断唤醒了一个更高优先级进程 | 抢占式系统下切换 | 就绪队列里出现了比当前进程更该运行的进程 |
| 缺页故障 | 调页期间当前进程阻塞,切换;调页完成后重新执行原指令 | 调页要访问磁盘,不能让 CPU 干等 |
时钟中断是抢占式调度得以成立的物理基础:正因为时钟会周期性地把控制权强行夺回内核,OS 才有机会重新做调度决定。没有时钟中断,一个不主动放弃 CPU 的进程将永远占据处理器。切换的具体动作(保存/恢复上下文)见上下文及其切换机制。
中断这个主题在操作系统与计算机组成原理里各关心什么(想弄清本文的边界时展开)
| 维度 | 操作系统视角(本文) | 计算机组成原理视角 |
|---|---|---|
| 关心什么 | OS 如何夺回控制权、切换内核态、是否引发进程切换 | 硬件如何识别中断信号、中断隐指令的组成、优先级判别电路 |
| 典型对象 | 进程、PCB、内核态/用户态、系统调用流程、屏蔽字的策略含义 | 向量地址形成电路、屏蔽字的赋值时机与排队器实现、中断响应周期时序 |
中断隐指令的微操作时序、屏蔽字寄存器的硬件实现属于硬件层面,本文点到即止。
考点速记
- 广义中断分外中断(异步、指令执行完毕后检测)与内中断/异常(同步、指令执行过程中检测);内中断按返回位置分 Trap(下一条)/ Fault(重新执行当前条)/ Abort(终止),缺页属 Fault。另一套口径按中断源分五类,与前者切在不同维度上。
- 软硬件分界的好用判据:要动 PC / PSW / 模式位的都是硬件,用普通指令做得成的才是 OS。断点(PC、PSW)由硬件存,现场(通用寄存器)由软件存。
- 中断"发生时"通常仍在用户态,处理程序"开始执行时"必然在内核态——前者是原因,后者是结果。
- 判断一条指令会不会引起态切换:是不是主动陷入指令 + 执行中可不可能触发异常,两条都不沾的纯寄存器运算才"绝不切换"。
- 定位入口走中断号 → 向量地址 → 向量 → PC,中断向量地址不是入口地址,中间差一次访存;表驱动使耗时与中断源数量无关。
- 单重中断全程关中断,多重中断保护完现场即开中断,靠优先级(设计时定死)+ 屏蔽字(运行时设置)共同决定谁能打断谁。
- 中断必然进内核态,但不必然引起进程切换——只有 OS 决定重新调度时才切。反过来"进程切换必然发生在内核态"成立。
这一节在真题里被考过的形式:
出题密度高,且几乎全在"分界"上做文章——软件与硬件的分界、两个时刻的分界、 库函数与系统调用的分界。记住分界,题就没有难度。
- 给三件事,问哪些会导致用户态切到内核态(2013-28)。答整数除以零 + read 系统调用,
sin()不切换。分界是"这件事用户态能不能自己完成"——算正弦值能,所以sin()全程在用户态;访问文件系统不能,所以read必须陷入。⚠️ 库函数不是系统调用,C 标准库里大部分函数根本不进内核。 - 给四条具体指令,问哪条不可能导致态切换(2015-24)。答
NOT R0。INT n是主动陷入必然切;DIV可能除零;MOV R0, addr可能缺页;只有纯寄存器取非两条判据都不沾。⚠️ 这道题问的是"不可能",要逐条找出"有没有任何一条路径能引出切换",漏想缺页就会误选 D。 - 问系统调用过程中哪些操作由操作系统完成(2022-31)。答保存通用寄存器 + 执行系统调用服务程序。保存断点和 PSW、把模式位改成内核态这两件都是硬件做的。⚠️ 这道题就是"要动 PC/PSW/模式位的都是硬件"这条判据的直接考法。
- 判断中断和异常的四条叙述,选错误的(2024-23)。错项是"中断或异常发生时,CPU 处于内核态"——发生的那一瞬间通常还在用户态。同题的 C 项"中断处理程序开始执行时 CPU 处于内核态"是对的。⚠️ A 与 C 只差"发生"和"开始执行"两个词,是本节被利用得最狠的一处时刻差。
复习优先级:必须拿满,且这一节的判据在系统调用那篇会原样再用一遍。 Trap/Fault/Abort 的返回位置、软硬件分工、两个时刻的差别,这三处每一处都单独出过题。 多重中断的时间线计算至今没进过选择题,但它是理解屏蔽字的必要一步,读懂即可。
易错:说"中断发生时 CPU 处于内核态"。发生的那一刻通常仍在用户态;处理程序开始执行时才必然在内核态。
易错:把库函数调用当成系统调用。
sin()这类纯计算函数全程在用户态,不引起任何切换。
易错:把"中断向量地址"当成中断服务程序入口。向量地址是表项自身的地址,按它访存取出来的才是入口地址。
易错:把保存断点和保存现场混为一谈。断点(PC、PSW)由硬件保存,现场(通用寄存器)由软件保存。
易错:认为访存指令不可能引起态切换。它可能缺页或越界,属于"可能"。
易错:由"中断必然进内核态"推出"中断必然引起进程切换"。普通系统调用返回后仍是同一进程。
易错:认为一开头就关中断所以不可能嵌套。那描述的是单重中断;多重中断在保护完现场之后会重新开中断。
教材出处
- 孙钟秀、费翔林《操作系统教程》(第 6 版)2.2.1 中断的概念(p44~p45):"可以说操作系统是由中断驱动的";广义中断划分为狭义中断、异常和系统异常三大类。
- 同书 2.2.2 中断源(p45~p47):五类中断事件(硬件故障中断、程序性中断、自愿性中断、I/O 中断、外部中断)及各自的处理原则,包括"非法指令、用户态使用特权指令、地址越界、非法存取等指令异常:终止进程"与"虚拟地址异常:……需要调整主存后重新执行指令"。
- 同书 2.2.3 中断系统(p47~p48):指令执行周期后加入"检查中断"的微操作;中断装置分为中断控制器、系统陷入机制与指令陷入机制三类。
- 同书 中断屏蔽与中断优先级、多重中断事件处理(p51~p52):中断屏蔽的三个用途;中断优先级"一般来说……依次为硬件故障中断、自愿性中断、程序性中断、外部中断和 I/O 中断",且不同系统可不同;"中断嵌套处理一般以不超过三重为宜";"中断嵌套处理改变了中断处理的先后次序,先响应的中断反而被延后处理"。
- 同书 2.1 处理器·用户栈和核心栈(p44):核心栈"保存中断现场,对于嵌套中断,将被中断程序的现场信息依次压入核心栈,中断返回时逆序弹出"。
相关知识
CPU运行模式(内核态与用户态)|系统调用|上下文及其切换机制