处理器按照一定的序列的地址执行对应的指令,从这一个地址过渡到下一个地址成为控制转移,这样的控制转移序序列称为处理器的控制流(flow control)

系统必须能够对系统状态的变化做出反应,这些系统状态不是被内部程序变量捕获的,而且也不一定要和程序的执行相关。比如,一个硬件定时器定期产生信号,这个事件必须得到处理。当子进程终止时,创造这些子进程的父进程必须得到通知。

现代系统通过使控制流发生突变(如缺页异常、网络等待)来对这些情况做出反应。一般而言,我们把这些突变称为异常控制流(Exceptional Control Flow, ECF)。异常控制流发生在计算机系统的各个层次。比如,在硬件层,硬件检测到的事件会触发控制突然转移到异常处理程序。在操作系统层,内核通过上下文转换将控制从一个用户进程转移到另一个用户进程。在应用层,一个进程可以发送信号到另一个进程,而接受者会将控制突然转移到它的一个信号处理程序。一个程序可以通过回避通常的栈规则,并执行到其他函数中任意位置的非本地跳转来对错误做出反应。

8.1 异常

异常是异常控制流的一种形式,它一部分是由硬件实现的,一部分是由操作系统实现的。因为它们有一部分是由硬件实现的,所以具体细节将随系统的不同而有所不同。然而,对于每个系统而言,基本的思想都是相同的。

异常(exception)是为了应对某些事件(event),控制由用户向操作系统内核的转移。事件(event)是指处理器状态的改变。这些事件包括被0除、算术溢出、缺页、I/O请求完成。

Untitled

在任何情况下,当处理器检测到有事件发生时,它就会通过一张叫做异常表(exception table)的跳转表,进行一个间接过程调用(异常),到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序, exception handler)

当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下三种情况中的一种:

8.1.1 异常处理

系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号(exception number)。其中一些号码是由处理器的设计者分配的,其他号码是由操作系统内核的设计者分配的。前者的示例包括被零除、缺页、存储器访问违例以及算术溢出。后者的示例包括系统调用和来自外部 I/O 设备的信号。

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

Untitled

异常号是到异常表中的索引,异常表的起始地址放在一个叫做异常表基址寄存器(exception table base register)的特殊 CPU 寄存器里。

Untitled