中断和异常的概念

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 响应中断时的一串硬件动作
  • 中断处理九步及软硬件分界;第 ⑤ 步开中断是为了中断嵌套,第 ⑦ 步关中断是为了保护恢复现场

链接