在给处理器加电开始,直到你断电为止,程序计数器假设一个值序列

$$ a_0,a_1,\cdots,a_{n-1} $$

其中,每个 $a_k$ 是每个相应的指令 $I_k$ 的地址。每次从 $a_k$ 到 $a_{k+1}$ 的过渡称为控制转移(control transfer)。这样的控制转移序列叫做处理器的控制流。

最简单的一种控制流是一个“平滑的”序列,其中每个 $I_k$ 和 $I_{k+1}$ 在内存中都是相邻的。(这种)平滑流的突变(也就是 $I_{k+1}$ 与 $I_k$ 不相邻)通常是由注入跳转,调用和返回这样一些熟悉的程序指令造成的。这样一些指令都是必要的机制,使得程序能够对由程序变量表示的内部程序状态中的变化作出反应

现代程序通过控制流发生突变来对这些情况(硬件定时器信号、包到达网络适配器、子进程终止等系统状态变化)做出反应。一般而言,我们把这些突变称为异常控制流(Exceptional Control Flow,ECF)

异常

异常(exception)就是控制流中的突变,用来响应处理器状态中的某些变化

状态变化称为事件

在任何情况下,当处理器检测到有事件发生时,它会通过一张叫做异常表的跳转表,进行一个间接过程调用(异常),到一个专门设计用来处理这类事件的操作系统子系统(异常处理程序(exception handler))。当异常处理程序完成处理后,根据引发异常的事件类型,会发生以下3种情况的1种:

  1. 处理程序将控制返回给当前指令 $I_{curr}$,即当事件发生时正在执行的指令
  2. 处理程序将控制返回给 $I_{next}$,如果没有发生异常将会执行的下一条指令
  3. 处理程序终止被中断的程序

异常处理

系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号。其中一些号码是由处理器的设计者分配的。其他号码有由操作系统内核(操作系统常驻内存的部分)的设计者分配的。

前者的示例包括被零除、缺页、内存访问违例、断点以及算术运算溢出。

后者的示例包括系统调用和来自外部 I/O 设备的信号。

在系统启动时,操作系统分配和初始化一张称为异常表的跳转表,使得表目 $k$ 包含异常k的处理程序的地址。

异常号是到异常表中的索引,异常表的起始地址放在一个叫做异常表机制寄存器的特殊CPU寄存器中。

异常的类别