linux系统中断详解


最近为了解决风控问题,一直在研究linux的系统内核,经过一段时间的学习,先整理出一份关于linux中断的小记。
1.什么是中断?
计算机cpu在执行task时,不可能每次都将任务执行完毕,会因为各种不同的场景而暂停执行,所谓中断就是这个暂停执行的过程。
2.中断算是一种错误吗?
严格来说,中断当然算是运行错误的一种,但是,由于其不可避免,程序开发者自然可以将其视为一种机制,加以运用,反而更容易帮助我们完成现实功能的实现。
3.中断的分类
从产生原因上看,中断可以分为软件中断和硬件中断,而从类别划分上看,也可以氛围有出错码中断和无出错码中断。二者并不排斥,比如说,中断分类存在int0~int255中,其中int0 ~ int31 表示软件中断,int32 ~ int255: 可由用户自己设置。其中int32 ~ int47 对应8259A的IRQ0 ~ IRQ15中断。需要注意的是,int128 为系统调用中断(system_call)。
如果大家有看过内核源码或者其他汇编代码,会发现汇编语言在调用c函数时,就是使用system_call,由此可见,调用其他函数,也是一种中断。这里不止局限于linux系统,其中中断逻辑囊括所有计算机逻辑执行逻辑,其最基础的实现逻辑就是计算机0/1与或逻辑,属于机器语言中最低级也是最高效的展现形式。
4.中断时堆栈变化情况
堆栈相关知识此处不做介绍,不了解的同学可以自行查找一下相关资料。

上图可以非常清楚的展示中断发生时堆栈的变化情况。即中断发生前,需要将图中的信息按照先后顺序,压入中断处理程序的堆栈中。下面进行具体的分析:
SS(stack segment): 堆栈段
ESP(extended stack pointer): 堆栈指针
EFLAGS : 状态标志寄存器
CS(code segment): 代码段
EIP(extended instruction pointer) : 中断后要执行的下一条指令的地址
1)有/无 出错码:我们只需知道,对于某些中断,比如:int0(无错误码) 是不需要保存出错码的,而像int8等中断是需要保存出错码的。所以对于不同的中断,堆栈变化不同。需要保存出错码的,必须在堆栈最后压入出错码。
2)有/无 优先级变化:如果中断发生前处于用户态(优先级3级),发生中断时需要变为内核态(优先级0级),我们称其为中断时的优先级发生了变化。对于优先级变化的中断,需要在堆栈的一开始压入 SS 和 ESP , 它们分别代表用户态下的堆栈段和堆栈指针。
这里需要解释一下,为什么中断发生时,需要先把信息数据压入栈中,主要是为了中断发生后,可以从栈中取出,从而执行中断时,可以从栈中获取到之前的数据,类似于一个逻辑上下文的处理。
中断过程就是 “中断前,将当前数据压入堆栈” -> “asm.s 调用 traps.c 处理中断程序”-> “中断完成后,将数据压出堆栈,恢复状态”
5.中断处理文件,asm.s
第四条最后,提到了俩个文件,asm.s和traps.c。这里的.c文件,大家应该都可以猜到,就是c语言编写的函数文件,asm.s则涵盖了int0 ~ int15中除int7,int14之外的一共14个中断处理程序。还记得吗?它们都是Intel固定设置的软件中断。
asm.s 程序的核心是以下两个函数:no_error_code和error_code。他们分别表示的是无出错码中断和有中断码中断。
no_error_code源码如下

error_code源码如下


6.中断处理文件traps.c
traps.c是一个c语言编写的实现文件,其中的函数多用于给asm.s文件调用。在asm.s文件的汇编代码中,call *****即为调用c函数,但是被调用的函数需要在文件顶部的“.globl”进行声明才能调用。
traps.c的核心函数是die函数,其源代码如下:

die函数的主要功能是打印错误信息,对于Inter这些固定的软件中断(int0 ~ int16),当发生时,我们所做的也就是打印出中断的名称,出错号,寄存器信息,进程信息等等。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM