中断和异常的概念
1.3.1 列出了进入内核的三种受控入口,这一节把其中两种(中断与异常)讲透,第三种系统调用放到下一节。
中断机制是操作系统能够”管起来”的前提。没有它,操作系统一旦把 CPU 交给用户程序,就再也拿不回来了——用户程序不主动交还,操作系统连插话的机会都没有。时钟中断的存在,正是抢占式调度得以成立的唯一原因。
机制
中断的作用
中断使 CPU 能够与其他设备并行工作。 CPU 启动 I/O 后不必等待,可以转去执行别的程序;设备完成时用中断来通知 CPU。这正是 5.1.2 中断驱动方式的基础。
中断也是操作系统夺回控制权的唯一手段。 时钟中断周期性地打断当前程序,让操作系统有机会重新做调度决策。
中断与异常的分类
顶层的划分只有一条判据:这个事件来自 CPU 外部还是内部。
外中断(狭义的”中断”)——来自 CPU 执行指令以外的事件,与当前执行的指令无关。例如时钟中断、I/O 完成中断、键盘输入。它又分为可屏蔽中断(可以被暂时屏蔽,稍后再处理)与不可屏蔽中断(通常是紧急的硬件故障,不允许被忽略)。
内中断(异常、例外、陷入)——来自 CPU 执行指令内部的事件,与当前执行的指令直接相关。它又分为三类,三类的差别在于”处理完之后怎么办”:
陷入(trap)——由陷入指令引发,是应用程序有意为之的,典型就是系统调用。处理完毕后返回到陷入指令的下一条指令继续执行。
故障(fault)——由错误条件引起,但内核程序有可能把它修好。典型是**缺页**:页不在内存里是个”错误”,但操作系统可以把页调进来。修复之后返回到引起故障的那条指令,重新执行它。
终止(abort)——由致命错误引起,不可修复,如除零、非法指令、特权指令错。程序无法继续,不返回原程序,通常直接终止该进程。
中断的处理过程
教材给出的九步流程,可以按”硬件做的”和”软件做的”分成两段来记:
① 关中断 —— 防止在保存现场的过程中又被新的中断打断。 ② 保存断点 —— 保存被中断程序的下一条指令地址(PC)。 ③ 引出中断服务程序 —— 根据中断类型找到对应服务程序的入口地址。
以上三步由硬件自动完成,合称”中断隐指令”——它不是一条真正的指令,机器指令系统里找不到它,它是 CPU 在响应中断时自动执行的一串硬件动作。
④ 保存现场和屏蔽字 —— 保存通用寄存器等现场信息。 ⑤ 开中断 —— 允许更高优先级的中断打断本次处理。 ⑥ 执行中断服务程序 —— 真正处理这次中断(如把数据从设备读进内存)。 ⑦ 关中断 —— 准备恢复现场,不能被打断。 ⑧ 恢复现场和屏蔽字 ⑨ 开中断、中断返回
以上六步由中断服务程序(软件)完成。
注意第 ⑤ 步和第 ⑦ 步这一开一关:开中断是为了让紧急的高优先级中断能够插进来(中断嵌套);关中断是因为恢复现场的过程不能被打断,否则现场会被搅乱。
边界
中断与异常的判据
判据是”与当前指令有没有关系”,而不是”严不严重”。
外中断与当前正在执行的指令毫无关系——时钟中断什么时候来,取决于时钟芯片,与当前程序在算什么完全无关。因此同一个程序两次运行,外中断到来的位置可能完全不同。
内中断由当前指令直接引发——同一个程序、同样的输入,两次运行会在完全相同的位置产生同样的异常。 除零指令每次执行都会除零。
由这条判据推出两个常考结论:异常不能被屏蔽(它是当前指令造成的,不处理就没法继续往下执行);外中断中的可屏蔽中断可以被暂时搁置(反正与当前指令无关,晚一点处理不影响正确性)。
三类内中断的返回位置不同
这是本节最值得记的一条,因为它直接对应第 3 章的一个高频考点:
| 类型 | 返回到哪里 | 典型例子 |
|---|---|---|
| 陷入 | 下一条指令 | 系统调用 |
| 故障 | 引起故障的那条指令(重新执行) | 缺页 |
| 终止 | 不返回 | 除零、非法指令 |
“故障要重新执行原指令”这一条,正是 3.2.2 中”缺页中断处理完毕后重新执行被中断的指令,而不是执行下一条”的来源。
理由很直白:那条指令根本没执行成功(它要访问的页当时不在内存)。页调进来之后,必须让它重来一次,否则这条指令的效果就丢了。
而系统调用属于陷入,它的陷入指令是执行成功了的,所以返回到下一条。
中断隐指令不是一条指令
“隐”字的含义是:它不出现在指令系统里,程序员写不出它,反汇编也看不到它。
它指的是 CPU 在响应中断时自动完成的那一串硬件动作——关中断、保存断点、跳转到中断服务程序入口。
这条辨析在 5.1.2 那道真题里考过:“在接收和处理输入设备中断的过程中,一定不由硬件完成的工作是什么”——保存断点、模式切换由硬件(中断隐指令)完成,而把数据从设备读进内存必须由中断服务程序(软件)完成。
扩展:信号是”进程级的中断”
本小节超出考纲,不必掌握。 收录它是因为这个类比能反过来加深对中断机制的理解。
操作系统中的信号是发给进程的异步通知,信息量很小,通常只是一个编号(如 SIGINT、SIGKILL、SIGSEGV)。
它与中断的结构高度相似,只是层次低了一级:中断打断的是 CPU 上正在执行的指令流,信号打断的是进程的执行流;中断有屏蔽字,信号有阻塞掩码;中断有服务程序,信号有处理函数。
最值得记的是它的处理时机:信号到来时,内核先把它记入目标进程的待处理集合,并不立即执行处理函数;真正的处理发生在该进程从内核态准备返回用户态之前——那是一个安全边界,此时现场是完整的。
这个时机与 1.3.1 中”调度发生在返回用户态之前”完全一致,原因也相同:内核只在自己完全掌握现场的那一刻,才去做改变控制流的事。
层次辨析:操作系统信号、GUI 框架的信号与前端事件循环
三者名字相近,但不在同一层次:操作系统信号是内核向进程发出的异步通知; **GUI 框架中的信号(如 Qt 的 signal/slot)**是对象之间的事件回调机制; 前端的事件循环是运行时的事件队列与回调调度模型。
以一次键盘输入为例,四层依次经过:键盘产生硬件中断 → 内核驱动读取扫描码并转为输入事件 → 窗口系统把事件投递给拥有焦点的应用 → 应用的事件循环分发给对应控件。
它们都体现”异步通知”这一思想,但只有第一步是操作系统意义上的中断。
对照速查
| 顶层分类 | 判据 | 又分为 |
|---|---|---|
| 外中断(中断) | 来自 CPU 外部,与当前指令无关 | 可屏蔽中断 / 不可屏蔽中断 |
| 内中断(异常、例外、陷入) | 来自 CPU 内部,与当前指令直接相关 | 陷入 / 故障 / 终止 |
| 内中断三类 | 起因 | 返回到哪 | 例子 |
|---|---|---|---|
| 陷入 trap | 有意引发 | 下一条指令 | 系统调用 |
| 故障 fault | 错误但可修复 | 引起故障的那条指令(重新执行) | 缺页 |
| 终止 abort | 致命错误 | 不返回 | 除零、非法指令 |
| 中断处理九步 | 谁完成 |
|---|---|
| ① 关中断 ② 保存断点 ③ 引出中断服务程序 | 硬件(中断隐指令) |
| ④ 保存现场和屏蔽字 ⑤ 开中断 ⑥ 执行中断服务程序 | 软件 |
| ⑦ 关中断 ⑧ 恢复现场和屏蔽字 ⑨ 开中断、中断返回 | 软件 |
| 为什么这样开关中断 | |
|---|---|
| ⑤ 开中断 | 允许更高优先级的中断嵌套进来 |
| ⑦ 关中断 | 恢复现场不能被打断,否则现场被搅乱 |
| 能否屏蔽 | 结论 |
|---|---|
| 异常(内中断) | 不能屏蔽——不处理就无法继续执行 |
| 可屏蔽中断 | 能——与当前指令无关,晚点处理不影响正确性 |
| 不可屏蔽中断 | 不能,通常是紧急硬件故障 |
考点
- 中断是操作系统夺回控制权的唯一手段,时钟中断是抢占式调度的前提
- 内中断 vs 外中断的判据是”与当前指令有没有关系”,不是严重程度
- 内中断三类的返回位置:陷入→下一条;故障→重新执行原指令;终止→不返回
- 缺页属于故障,因此处理后重新执行原指令(第 3 章高频)
- 异常不能被屏蔽,可屏蔽中断可以
- 中断隐指令不是一条指令,是 CPU 响应中断时的一串硬件动作
- 中断处理九步及软硬件分界;第 ⑤ 步开中断是为了中断嵌套,第 ⑦ 步关中断是为了保护恢复现场
链接
- 🏠 返回总览:操作系统第 1 章:计算机系统概述总览
- ⬅️ 上一节:1.3.1 处理器运行模式
- ➡️ 下一节:1.3.3 系统调用
- 🔗 缺页为何重新执行原指令,见 3.2.2 请求分页管理方式
- 🔗 中断驱动的 I/O 方式,见 5.1.2 I/O 控制方式
- 📖 名词库:第 1 章名词库