Linux中断和系统调用的解析

Linux中断和系统调用的解析

系统调用和中断的结构图

作者:番茄味的可比克
链接:https://www.zhihu.com/question/30432536/answer/54998416
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

中断:又称为异步中断,是其他硬件依照CPU时钟信号随机产生的。中断又被分为可屏蔽硬件中断不可屏蔽中断。在微机原理课程中,处理器中有两个引脚NMI和INTR负责接受中断信号,还有高级可编程中断控制器(APIC),如8259A管理中断信号。则可屏蔽硬件中断:任何通过INTR或着局部APIC传递到处理器的中断信号都被称为可屏蔽硬件中断,由IO设备产生的IRQ(Interrupt ReQuest)也是可屏蔽硬件中断。但是通过INTR引脚传递的可屏蔽硬件中断可使用Intel架构定义的中断向量(0-255),而局部的APIC传递的部分只能使用16-255号向量。若中断信号从NMI引脚传递过来,则发生的是一个不可屏蔽中断。

像我们常见的,键盘、网卡输入就是异步中断,异步中断(硬中断)的处理我们在汇编语言中已经学过了

不可屏蔽中断源一旦提出请求,cpu必须无条件响应,而对于可屏蔽中断源的请求,cpu可以响应,也可以不响应。cpu一般设置两根中断请求输入线:可屏蔽中断请求INTR(Interrupt Require)和不可屏蔽中断请求NMI(Nonmaskable Interrupt)。对于可屏蔽中断,除了受本身的屏蔽位的控制外,还都要受一个总的控制,即CPU标志寄存器中的中断允许标志位IF(Interrupt Flag)的控制,IF位为1,可以得到CPU的响应,否则,得不到响应。IF位可以有用户控制,指令STI或Turbo c的Enable()函数,将IF位置1(开中断),指令CLI或Turbo_c 的Disable()函数,将IF位清0(关中断)。

典型的非屏蔽中断源的例子是电源掉电,一旦出现,必须立即无条件地响应,否则进行其他任何工作都是没有意义的。

典型的可屏蔽中断源的例子是打印机中断,CPU对打印机中断请求的响应可以快一些,也可以慢一些,因为让打印机等待儿是完全可以的。
————————————————
版权声明:本文为CSDN博主「lidandan2016」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lidandan2016/java/article/details/53437273

异常:又称为同步中断,是当指令执行时CPU控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后CPU才会发出中断。在不失进程执行连续性的同时,按引起的异常的指令是否能重新执行,且依据它们被报告的方式,异常分为错误陷阱,和终止三种情况。

错误:错误是一种通常可以能够被修正的异常,一旦修正,程序能够不失去连续性地接着执行。当报告错误发生时,处理器将机器状态恢复到执行错误之前的状态。错误处理例程的返回地址指向产生错误的指令,而不是错误指令之后的的那条指令。如页错误。

陷阱:当引起陷阱的指令发生时,马上产生该异常。陷阱允许程序不失去连续性的继续执行。陷阱处理例程的返回地址指向引起陷阱的指令的下一条指令(与错误本质上的区别)。如溢出。

终止:它并不总是报告产生异常的指令的确定位置,也不允许引起终止的进程或任务重新执行。如总线错误导致异常终止。


Linux中的中断向量:

0-19的中断向量对应于异常和非屏蔽中断。

20-31Intel保留

32-127可屏蔽硬件中断

128用于系统调用的可编程异常

129-238可屏蔽硬件中断

239本地APIC时钟中断

240本地APIC高温中断

241-250由Linux留作将来使用

251-253处理器间中断

254本地APIC错误中断

255本地APIC伪中断(CPU屏蔽某个中断时产生的)

软中断又叫做编程异常,主要用于执行系统调用即*int 0x80*以及给调试程序通报一个特定的事件,所以软中断是异常的一种,属于同步中断。

而我们的系统调用又是基于软中断实现的:注意,我说的是系统调用是基于软中断实现的,而不是说系统调用就是软中断!这一点看下面的系统调用原理就知道了

Linux中断和系统调用过程

之后我们主要研究系统调用、其他异常和硬中断,所以我们在以后就把硬中断简称为中断,也使用异常、系统调用以示区分

中断、异常和系统调用处理流程

借助这副图我们可以看到,用户程序和内核之间的交互主要是通过系统调用实现的,而内核和外部设备之间主要是通过硬中断

系统调用的执行过程

  1. 通过特定指令发出系统调用(int 0x80、sysenter、syscall)

    这个int 0x80就是用于系统调用的可编程异常,当然这只是实现方法之一,由于通过中断方式发起系统调用的性能较差,较新的CPU和内核都支持使用sysenter和syscall这两条专用指令来发起系统调用。其中sysenter在32位系统中使用,对应的退出指令为sysexit;syscall在64位系统中使用,对应的退出指令为sysret。

  2. CPU从用户态切换到内核态,进行一些寄存器和环境设置

  3. 调用system_call内核函数,通过系统调用号在系统调用表中获取对应的服务例程

  4. 调用系统调用处理例程

  5. 使用特定指令从系统调用返回用户态(iret、sysexit、sysret)

可以看到,和硬件中断不同,软中断基本上是由操作系统的内核处理的。而所有的系统调用也只使用了一个中断向量

硬件中断的执行过程

  1. 驱动设备将自己的中断处理程序写入内核,在加载内核的时候将中断向量表初始化,中断向量表中有驱动程序处理中断的函数的中断向量

中断向量:是指中断服务程序入口地址的偏移量与段基值,一个中断向量占据4字节空间。中断向量表是8088系统内存中最低端1K字节空间,它的作用就是按照中断类型号从小到大的顺序存储对应的中断向量,总共存储256个中断向量。在中断响应过程中,CPU通过从接口电路获取的中断类型号(中断向量号)计算对应中断向量在表中的位置,并从中断向量表中获取中断向量,将程序流程转向中断服务程序的入口地址。

  1. CPU在指令周期的执行周期末进行检测查看有无中断,有中断请求且可以处理时就进入中断周期,开始做准备工作,保存断点,确定中断向量(中断处理程序入口地址),然后置为PC,之后就又是取指、执行了。

  2. 底层的外部设备和计算机通信使用的就是中断:硬件(比如说键盘按了一下)触发了一个电信号,这个信号通过中断线到达中断控制器i8259A,i8259A接受到这个信号后,向CPU发送INT信号申请CPU来执行刚才的硬件操作,并且将中断类型号也发给CPU

  3. CPU中断后去查中断向量表,找到中断服务例程,例程调用对应的设备驱动与外部设备之间通信

可以看到,硬件中断中基本是CPU的工作,涉及到操作系统内核的部分很少

关于中断向量的细节以及实现,可以看这篇文章:https://www.cnblogs.com/frankyou/p/8649435.html

Reference

  1. https://blog.csdn.net/weixin_41376979/article/details/83756975?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
  2. https://www.cnblogs.com/answercard/p/4288431.html
  3. https://www.zhihu.com/question/30432536
  4. https://blog.csdn.net/dillanzhou/java/article/details/82733562
  5. https://www.cnblogs.com/frankyou/p/8649435.html
posted @ 2020-03-31 18:01  别再闹了  阅读(2991)  评论(0编辑  收藏  举报