从给处理器加电开始,直到你断电为止,程序计数器假设一个值的序列
其中,每个是某个相应的指令
的地址。每次从
到
的过渡称为控制转移(control transfer)。这样的控制转移序列叫做处理器的控制流(flow of control或control flow)。
最简单的一种控制是一个“平滑的”序列,其中每个和
在内存中都是相邻的。这种平滑流的突变通常是由诸如跳转、调用和返回这样一些程序指令造成的。我们把这些突变称为异常控制流(exceptional control flow,ECF)。
异常
异常是异常控制流的一种形式,它一部分由硬件实现,一部分由操作系统实现。
异常(exception)就是控制流中的突变,用来响应处理器状态中的某些变化。
异常刨析图:
在图中,当处理器状态中发生一个重要变化时,处理器正在执行某个当前指令。在处理器中,状态被编码为不同的位和信号。状态变化称为事件(event)。事件可能和当前指令的执行直接相关。比如,发生虚拟内存缺页、算术溢出,或者一条指令试图除以零。另一方面事件也可能和当前指令的执行没有关系。比如,一个系统定时器产生信号或者一个I/O请求完成。
在任何情况下,当处理器检测到有事件发生时,它就会通过一张叫做异常表(exception table)的跳转表,进行一个间接过程调用(异常),到一个专门设计用来处理这类事件的操作系统子程序(异常处理程序(exception handler))。当异常处理程序完成处理后,根据引起异常的事件的类型,会发生以下3中情况中的一种:
- 处理程序将控制返回给当前指令
,即当事件发生时正在执行的指令。
- 处理程序将控制返回给
,如果没有发生异常将会执行的下一条指令。
- 处理程序终止被中断的程序。
异常处理
系统中可能的每种类型的异常都分配了一个唯一的非负整数的异常号(exception number)。其中一些号码是由处理器的设计者分配的,其它号码是由操作系统内核(操作系统常驻内存的部分)的设计者分配的。
在系统启动时,操作系统分配和初始化一张称为异常表的跳转表,使得表目k包含异常k的处理程序的地址。
在运行时,处理器检测到发生一个事件,并且确定了相应的异常号k。随后,处理器触发异常,方法是执行间接过程调用,通过异常表的表目k,转到相应的处理程序。
异常号是到异常表中的索引,异常表的起始地址放在一个叫做异常基址寄存器(exception table base register)的特殊CPU寄存器里。
异常的类别
- 中断(interrupt):中断是异步发生的,是来自处理器外部的I/O设备的信号的结果。硬件中断的异常处理程序常常称为中断处理程序(interrupt handler)。总是返回到下一条指令。
- 陷阱和系统调用(trap):陷阱是有意的异常,是执行一条之后零的结果。陷阱最重要的用途是在用户程序和内核之间提供一个像过程一样的接口,叫做系统调用。总是返回到下一条指令。
- 故障(fault):故障是由错误情况引起的,它可能能够被故障处理程序修正。可能返回到当前指令。
- 终止(abort):终止是不可恢复的致命错误造成的结果,通常是一些硬件错误。不会返回。
进程
异常是允许操作系统内核提供进程(process)概念的基本构造块,进程是计算机科学中最深刻、最成功的概念之一。
进程的经典定义就是一个执行中程序的实例。
进程提供给应用程序的关键抽象:
- 一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占的使用处理器。
- 一个私有的地址空间,它提供一个假象,好像我们的程序都炸的使用内存系统。
逻辑控制流
即使在系统中通常有许多其它程序在运行,进程也可以向每个程序提供一种假象,好像它在独占的使用处理器。用调试器单步执行程序,我们会看到一系列的程序计数器的值,这些值唯一的对应于包含在程序的可执行目标文件中的指令,或是包含在运行时动态链接到程序的共享对象中的指令。这个PC值的序列叫做逻辑控制流,或者简称逻辑流。
并发流
一个逻辑流的执行在时间上与另一个流重叠,称为并发流(concurrent flow),这两个流被称为并发的运行。
多个流并发的执行的一般现象被称为并发(concurrent)。一个进程和其它进程轮流运行的概念称为多任务(multitasking)。一个进程执行它的控制流的一部分的每一时间段叫做时间片(time slice)。因此,多任务也叫做时间分片(time slicingÿ