计算机中断机制
现代计算机无一不实现中断机制,让各种执行速度不一的任务相互中断,抢占CPU。下表列出五种常见中断类型:
- 程序性中断:在程序执行的过程中,发现了程序性质的错误或出现了某些特定状态而产生的中断。如浮点溢出、用户态下使用了特权指令、内存越界、跟踪等。
- 外中断:对某个中央处理机而言,它的外部非通道式装置所引起的中断称为外部中断。例如,时钟中断、操作员控制台中断,多处理机系统中CPU到CPU之间的通信中断等。
- 输入输出中断:它是当外部设备或通道操作正常结束或发生误时所发生的中断。例如:打印机打印完成、缺纸,读磁盘时相应驱动器中没有磁盘等。
- 硬件故障中断:当机器发生故障时的中断叫硬件故障中断。例如,电源故障、内存单元奇偶校验错。
- 访管中断:对操作系统提出某种请求时所发生的中断。例创建进程,I/O传输、打开文件、关闭文件、文件的读、写等系统调用。
中断的引入是为了提高CPU的利用率,因为很多外部设备远远慢于CPU的速度。假如CPU以如下的指令周期模式发送数据给打印机进行打印,每发出一 个写操作CPU必须暂停并等待打印机把刚发送的数据打印才能进行下一个写操作。CPU的等待的时间可达到四五个甚至六个数量级(百万)个指令周期。
举一个具体的例子,假如CPU的速度是1G,指令执行速度约十亿条每秒(10^9)。一个一般的硬盘理想的情况下转速是7200转每分钟,每转半轨为4毫秒,也就是说比CPU慢4百万倍。
下图的A部分展示了这种没有中断处理的I/O操作。用户程序有两处的I/O操作。垂直实线代表程序(包括I/O程序)的代码段。
代码段1、2和3都没有I/O操作,不过它们之间有两处写操作,写操作会调用属于操作系统一部分的I/O程序。I/O程序由三部分组成:
第一部分是准备阶段。图中标号为4的部分,负责为实际的I/O操作作准备,包括拷贝数据到设备缓冲和为设备命令准备好参数。
第二部分是I/O命令执行阶段。也可以说是等待I/O阶段,因为没有中断机制时,操作命令一下达,I/O程序(也代表CPU)必须等待IO设备完成指定任务,I/O程序能作是只不断地测试设备的状态寄存器,看看设备完成工作没有。
第三部分是完成处理阶段。图中标为5的代码段。完成处理包括设置状态位标识IO操作的成功与失败。
图中虚线代表处理器的执行路线,也就是指令的执行序列(KEMIN:程序代码与处理器执行是一体两面,经常分开讲,其实经常指是是一个东西)。
由于I/O操作一般需要一个相对较长的时间完成,所以I/O程序(也包括用户程序)在IO操作期间被挂起,甚至整个系统都在等待。
P.S.没有中断机制的I/O操作,I/O处理例程更像是用户程序的一部分,像是一个子程序的调用,完全同步,没有上下文切换。
中断与指令周期
有了中断以后,CPU可以与I/O操作一并运行。参考上图中的B部分。与A部分类似,用户程序在调用了写操作后进入I/O程序,不过这次I/O程序在完成 准备阶段任务后便立即返回到用户程序,用户程序与I/O设备并发工作(KEMIN:细心想想,这种并发性是用户程序本身决定的,换个角度看,如果是读操 作,那么用户程序要不要等呢?答案应该是肯定的,至少与读出数据相关的任务必须等,只是用户程序可执行另一个并发任务,比如显示一个读操作的进度条)。
b.上下文切换是多道程序的特征和必要。但是有一种切换迷惑了我们,就是协作式任务的切换,比如系统服务或硬件驱动调用。细心想想,其实切换的本质是换工 作内容。由WORD切换到音乐播放器是进程切换;由WORD里的拼写检查到接受用户输入的切换是线程切换。而由音乐播放器解码到声卡驱动将解码数据输出的 切换则是一种伪切换,它是一个无法分解的任务前后部分,但是因为要对硬件的保护而做成客户服务形式。这个过程中,音乐播放器的主线程被挂起,而声卡驱动输 出可能不需要音乐播放器的主线程的任何信息(这就是所谓的无关上下文任务),完成后就绪(具体可能置一下音乐播放器的主线程某状态位)音乐播放器的主线 程…… 2009-4-23 12:44
当外部设备完成了写操作,准备了接受处理器更多的数据时,设备的I/O模块(控制器)向处理器发出一个中断请求信号。如果中断响应的条件满足,处理器便挂 起当前的用户程序(假设只有一个程序在计算机内执行),转向某特定中断处理程序(interrupt handler),完成中断处理后恢复先前用户程序的执行。图中用一个叉表示中断点,这个点发生的时刻是任意的。就是因为中断发生不可预见性,用户程序本 身是无法进行中断现场保存及恢复,这个工作必须由处理器和操作系统(中断处理程序)负责。
CPU为了提供中断机制,CPU的指令周期(instruction cycle)增加了中断(判断)阶段(interrupt stage),如下图。在中断判断阶段,处理器检查是否有中断发生,根据引脚是否中断信号。如果没有中断等候(pending)处理,处理返回取指阶段 (fetch stage),继续下一轮指令周期;如果有中断等候处理,那么处理器便挂起当前的用户程序并转中断处理程序。一般来说,中断处理程序是操作系统的一部分。 中断处理程序一般会先判断中断源(determines the nature of XX)再作相应的处理。比如本例子中,处理程序会判断哪个I/O控制器发出的中断请求……
b.又来了一个问题,跨进程(线程)的中断是怎样触发的?硬件中断有引脚,而用户进程要进入核态可以自己发出软中断,但是一个优先更高的线程(比如OS的 进程调度线程)怎么打断当前进程,占用CPU的呢?那只有一种可能,就是CPU每执行一条指令后都会检查有没有优先更高的线程要中断处理,是这样的吗? 2009-4-13 11:34
很明显,中断调用与返回过程会有额外的开销(相对了同步的轮询)。不过相对于等待I/O操作,CPU完成中断现场保存与恢复和中断源的判断所需的指令时间是微不足道的。
中断处理过程
从中断产生的一刻开始,系统内(包括处理器和软件)会有一系列的事件发生。下图展示了这些事件发生的流程:
硬件事件
- 设备向处理发生中断请求信号;
- 在响应中断请求前,处理必须完成当前的指令执行任务;
- 处理器在中断判断期(interrupt stage)检测到中断请求,然后发一个确认信号(acknowledgment signal )给中断设备;接到确认后,设备移去线路上的中断请求信号。
- 中断响应的第一步是保存中断现场。为了能恢复中断现场,处理器至少保存程序状态字(program status word PSW)和程序计数器(program counter)的值。这些状态值会被压入系统控制堆栈(system control stack)
P.S.请补充系统堆栈具体是什么? - 中断响应的第二步是载入中断处理程序。这个过程只需把中断处理程序的入口地址载入程序计数器即可。根据体系结构或操作系统设计的不同,可能有一个或多个入 口地址(每种中断源一个)。如果有多个入口地址,处理器还得先判断哪一个地址才是。入口地址信息可能包含当初的中断请求信号中,也可能需要处理器查询所有 设备而获得。
软件事件
-
中断过程到这一步,虽然被中断的用户程序的程序计数器和程序状态字已经被保存到控制堆栈,但是被中断的用户程序的其它状态信息还是要被注意的。比如,处理
器的寄存器内容要被保存,因为中断处理程序可能会用到这些值。中断处理程序的代码一开始就是负责保存这些状态信息(关于这些状态信息的具体详细,请参阅第
三章
进程描述与控制)。下图A部分简要的展示了这个过程中的内容。用户程序在N地址处被中断,然后所有寄存器值和下一条指令的地址(N+1)总共M个字被压入
控制堆栈。栈顶指针被更到新的位置,程序计数器也被更新为中断处理程序的首地址。
- 下一步是中断处理正式开始。中断处理的指令(或者叫任务)包括检测设备状态、下达处理命令等等,根据中断处理任务的不同而不同。
- 中断处理完成后进入中断现场的恢复——弹出控制堆栈的内容回原处。这些任务包含在中断处理程序中;
- 中断处理最后一步是恢复原中断程序的程序状态字和程序计数器的值(KEMIN:不明白为什么中断现场恢复分两步讲)。
为了正确地恢复原中断程序的执行,原中断程序的所有状态信息必须被保存起来,因为中断调用不是子程序调用,中断事件的发生是不可以预知的。