中断、异常、和系统调用的区别总结

中断、异常、和系统调用在OS和计算机组成原理中都经常被提到,很难区分,并且不同版本的教材往往有不同的说法。这里主要采用《CSAPP》中的说法区分一下中断、异常、和系统调用。

主要内容如下:

术语说明

  1. 逻辑控制流: 指的是程序从开始第一条指令之后,PC中产生的值序列 : a 1 , , a k , ,其中 a k 是指令 I k 的地址, I k + 1 I k 的下一条指令。其中 a k a k + 1 并不一定要是在内存中相邻的,也就是由于跳转,调用,返回,引起的指令地址不相邻的情况我们也称为下一条,简单地说就是 逻辑控制流是程序本身就可以预测到的指令序列
  2. 异常控制流 : 但是有些指令并不是可以在程序中预测到的,比如缺页异常,打印机缺纸,发生这种事件是不可预测的,我们将这种突变称为异常控制流。这里要说的中断,异常,系统调用都是异常控制流。但是有的书将他们统称为异常,或者中断,我们这里统称为异常控制流(Exception Control Flow,ECF), 简称异常流,以区分异常中断和系统调用。

异常流

按照指令执行图来解释可能更好理解:

这里写图片描述

不过这里的返回地址并不总是下一条指令,这里按照异常处理之后的返回地址分为3中情形:

  1. 处理器将控制返回给当前指令 I c u r , 即当事件发生时正在执行的指令
  2. 处理器将控制返回给 I c u r 的下一条指令,这里的下一条仅仅是逻辑上的,跳转,返回,或者调用的下一条,并不一定是内存上相邻的下一条,(:无特别说明均如此)
  3. 处理机终止程序。

异常流的处理

这里讲的是一个笼统的处理方式,不同的异常流可能会不一样。不涉及细节

  1. 保存现场,即保存PC和状态寄存器(PSW),IA-32中就是 EFLAGS
  2. 进入内核态
  3. 找到相应的处理程序(有一个异常流表记录了所有的异常流条目)
  4. 根据处理程序的结果返回

异常与过程调用的区别

  1. 返回地址,过程调用一定是将返回地址(逻辑流下一条指令)压栈,而异常可能是下一条指令,可能是当前指令。
  2. 处理器会把状态字寄存器压栈,而过程调用不会 这里考研经常考
  3. 异常流处理运行在内核模式下
  4. 如果控制从用户程序转到内核,所有的这些项目都被压倒内核栈中。

异常流的分类

分为4类:

类别 原因 异步/同步 返回行为
中断(interrupt) 来自处理机外部设备的信号(e.g. IO) 异步 总是下一条指令
陷阱(trap) 有意的异常 同步 总是下一条指令
故障(fault) 潜在可恢复错误 同步 可能返回当前指令
终止(abort) 不可恢复错误 同步 杀死程序,不返回

中断

这里的中断是特指来自外部的信号中断当前指令序列的执行。通常国内教材只有在特指外部中断时才指的是这个,而内部异常通常指的就是后三种.

陷阱

陷阱是有意的异常,重要的用途就是在用户程序和内核之间提供像过程调用一样的接口,称为系统调用,让用户程序能够访问操作系统提供服务,所以系统调用是陷阱的一种,同时陷阱只是内部异常的一种。在IA-32中陷阱指令有 INT n, int 3,into, bound etc.

故障

故障由错误引起,常见的比如segment fault, 缺页异常,如果系统能够处理,那就会回到当前指令继续执行,否则终止程序。

终止

就是不可恢复了。

Linux/x86-64 中的异常

0-31因特尔架构师定义的异常,32-255操作系统定义的,是 中断或者陷阱
常见的 printf函数就系统调用的包装,一般来说需要与操作系统打交道的,也就是需要请求系统服务资源(指的是外设)的就是内部异常了,外部中断是来自外部的信号。

总结

比较不清楚的就是异常和中断常常被国内的教科书用来指所有的异常流(上面4种),而只有在特指内部异常和外部中断时才区分异常来自外部还是程序内部。

猜你喜欢

转载自blog.csdn.net/dylan_frank/article/details/80698627