公众年夜众号:Rand_cs
中断,英文名为Interrupt,打算机的天下里处处都有中断,任何事情都离不开中断,可以说全体打算机系统便是由中断来驱动的。那么什么是中断?大略来说便是CPU停下当前的事情任务,去处理其他事情,处理完后回来连续实行刚才的任务,这一过程便是中断。
本文旨在进一步揭开中断机制的面纱,理清中断的过程,就中断做出以下几个方面的先容:中断分类,中断描述符表,中断掌握器,和中断过程。详细的思维导图如下:

中断分类
1
外部中断
1、可屏蔽中断:通过INTR线向CPU要求的中断,紧张来自外部设备如硬盘,打印机,网卡等。此类中断并不会影响系统运行,可随时处理,乃至不处理,以是名为可屏蔽中断。
2、不可屏蔽中断:通过NMI线向CPU要求的中断,如电源掉电,硬件线路故障等。这里不可屏蔽的意思不是不可以屏蔽,不建议屏蔽,而是问题太大,屏蔽不了,不能屏蔽的意思。
注:INTR和NMI都是CPU的引脚
2
内部中断(软中断,非常)
1、陷阱:是一种故意的,预先安排的非常事宜,一样平常是在编写程序时故意设下的陷阱指令,而后实行到陷阱指令后,CPU将会调用特定程序进行相应的处理,处理结束后返回到陷阱指令的下一条指令。如系统调用,程序调试功能等。
只管我们平时写程序时彷佛并没有设下陷阱,那是由于平常所用的高等措辞对底层的指令进行了太多层的抽象封装,已看不到底层的实现,但实在是存在的。例如printf函数,最底层的实现中会有一条int 0x80指令,这便是一条陷阱指令,利用0x80号中断进行系统调用。
2、故障:故障是在引起故障的指令被实行,但还没有实行结束时,CPU检测到的一类的意外事宜。出错时交由故障处理程序处理,如果能处理改动这个缺点,就将掌握返回到引起故障的指令即CPU重新执这条指令。如果不能处理就报错。
常见的故障为缺页,当CPU引用的虚拟地址对应的物理页不存在时就会发生故障。缺页非常是能够改动的,有着专门的缺页处理程序,它会将缺失落的物理页从磁盘中重新调进主存。而后再次实行引起故障的指令时便能够顺利实行了。
3、终止:实行指令的过程中发生了致命缺点,不可修复,程序无法连续运行,只能终止,常日会是一些硬件的缺点。终止处理程序不会将掌握返回给原程序,而是直接终止原程序
中断描述符表
中断描述符表类似全局描述附表,表内存放的描述符,与GDT不同的是IDT内可以存放4种描述符:任务门描述符,陷阱门描述符,调用门描述符,中断门描述符。
咱们在此只先容中断门描述符,4种描述符除了任务门其他都类似,中断门也是最常用的,如Linux的系统调用便是利用中断门实现的。
1
中断描述符
中断描述符的构造如上,主要字段和属性为已标出,有个理解就好,不必穷究各个位的详细含义。
2
中断向量号
在先容中断向量号之前,我们先引入一个段选择子(segment selector)的观点。所谓段选择子,便是段寄存器的值,段选择子的高13位为全局描述符表的索引号,其他的位置是属性位,这就好比是数组下标索引数组元素。
至于中断向量号,浸染等同于段选择子的高13位,用来在IDT中索引相对的中断描述符,但没有相应的类似段选择子的构造。
部分中断向量表,须要理解的部分如下图所示:
3
中断描述符表寄存器IDTR
IDTR也类似于GDTR,存放的是48位数据信息,高32位是IDT的地址,低16位表示IDT的界线。
同GDTR,IDTR也有相应的加载指令:lidt m16&32,m是那48位数据信息,lidt指令将其加载到IDTR寄存器,使得CPU知道IDT在哪。
中断掌握器
每个独立运行的外设都可以是一个中断源,能够向CPU发送中断要求,为了方便管理和减少引脚数目,设立了中断掌握器,让所有的可屏蔽中断都通过INTR旗子暗记线与CPU进行互换。
中断掌握器中较为盛行的是Intel 8259A芯片,下面对8259A作大略先容:
1
级联
单个8259A芯片只有8根中断要求旗子暗记线(IRQ0, IRQ1, … , IRQ7),这是不足用的,以是采取多个8259A芯片。将它们如下图一样像串联的办法组合起来,这种组合办法就叫做级联。
级联时只能有一个主片,别的的均为从片,最多可级联9个,即最多支持64个中断。为什么不是8 9 = 72个呢?从上图可以看出级联时后面的芯片会占用前面芯片的一个IRQ接口,而末了一个8259A没有其他人占用,以是8259A的个数和支持的中断数关系为7n + 1。
2
8259A的一些功寄存器和功能部件
1、IMR:Interrupt Mask Register,中断屏蔽寄存器,个中的每个位标志着一个外设,1表示屏蔽该外设,0表示中断许可。
2、IRR:Interrrupt Request Register,中断要求寄存器,要求中断的外设在IRR对应的位 值为1。当有多个中断要求时,IRR寄存器中多位将会置1,相称于坚持了一个要求中断的行列步队。
3、ISR:In_Service Register,中断做事寄存器,正在进行处理的中断在ISR对应的位值为1。
4、PR:Priority Resolver,优先级裁决器,用于从IRR中挑选一个优先级最大的中断。(IRQ接口号小的优先级大)。
中断过程
1
中断要求
1、当外设发出中断旗子暗记后,旗子暗记被送入8259A;
2、8259A检讨IMR寄存器中是否屏蔽了来自该IRQ的旗子暗记,若IMR寄存器中对应的位为1,表示屏蔽了IRQ代表的中断,则丧失落此中断旗子暗记,若IMR寄存器中对应的位为0,表示未屏蔽此中断,则将IRR寄存器中与此中断对应的位 置1。
3、PR优先级裁决器从IRR寄存器中挑选一个优先级最大的中断,然后8259A向CPU发送INTR旗子暗记。
2
中断相应
1、CPU收到INTR旗子暗记后便知道有新的中断了,在实行完当前指令后,向8259A发送一个中断回答旗子暗记。
2、8259A收到回答旗子暗记后,将选出来的优先级最大的中断在ISR寄存器中相应的位 置1,表示该中断正在处理,同时将此中断在IRR寄存器中相应的位 置0,相称于将此中断从中断要求行列步队中去掉。
3、CPU再次向8259A发送INTR旗子暗记,表示想要获取中断向量号。
4、8259A通过数据总线向CPU发送中断向量号,中断向量号 = 起始向量号 + IRQ接口号,一样平常起始向量号为32,从中断向量表可看出0—31已经被占用,后面的32—127是分配给可屏蔽中断的,以是此处外设的中断设置的起始向量号便为32。
3
保护现场——压栈
1、CPU据中断向量号去IDT中获取中断描述符,取出选择子中的DPL与当前特权级CPL进行比较,若特权级发生变革,则须要切换栈。(不同特权级有着不同的栈,如Linux利用了0, 3特权级,则有两个栈,一个内核栈,一个用户栈)
2、于是处理器临时保存当前的旧栈SS和ESP的值,从TSS(每一个任务有一个TSS构造,个中保存着不同特权级栈的SS和ESP值)中获取与DPL特权级同的栈信息加载到SS和ESP寄存器。再将旧栈SS和ESP的值压入新栈中。若没有特权级变革,则跳过此步骤。
3、压入程序状态信息,即EFLAGS寄存器
4、压入断点,即返回地址,即当前任务的CS,EIP值。
5、若该中断有缺点码,压入缺点码
4
定位中断做事程序
直接先上流程图:
详细步骤如下:
1、据中断向量号去IDT中索引中断描述符,详细操作:取出IDTR中的IDT地址,加上中断向量号 8,得到的地址指向所要的中断描述符。
2、据中断描述符中的段选择子去GDT中索引段描述符,详细操作:取出GDTR中的GDT地址。加上段选择子高13位 8, 得到的地址为中断处理程序所在段的段基址。
3、上一步得到的段基址加上段描述符中的段内偏移量得到的地址变为中断做事程序的地址。
5
中断处理过程
中断的实际处理过程便是实行中断处理程序,Linux将中断处理程序分为高下两部分,须要紧急处理立即实行的归为上半部,不那么紧急的归为下半部。
这便涉及到了开关中断的问题。开中断,即EFLAGS的IF位置1,表示许可相应中断;关中断,即EFLAGS的IF位置0,表示不许可相应中断。
1、上半部分是刻不容缓的,须要立即实行的部分,以是要在关中断的状态下实行。
2、而下半部分不那么紧急,在开中断的情形下进行,如果此时有新的中断发生,当前中断处理程序便会换下CPU,CPU会另寻韶光重新调度,完玉成部中断处理程序。
6
中断返回——出栈
中断返回便是出栈的过程,将第三步保护现场压入栈中的信息弹出。
1、有缺点码弹出错误码。
2、此时的栈顶指针ESP应指向EIP_old,剩余栈中的信息利用iret指令弹出,CPU实行到iret指令时再次检讨和比较特权级是否变革。
3、弹出EIP_old, CS_old
4、若特权级变革,将ESP_old, SS_old, 加载到ESP,SS寄存器。
至此,中断已返回,中断也已处理。
上述的中断过程是我根据资料照着自己的理解分为了6步,每步又有许多微操作,可能跟某些书本资料等所划分的步骤不同,乃至一些微操作的顺序也不太一样,比如说中断处理时什么时候关中断,我查阅了许多资料和书本,讲述得都有差异。
不同操作系统在中断方面的实现有所不同,但总体来说都会经历上述的步骤,可能细微之处略有差别,却也不影响我们理解中断的过程。
END
中断是操作系统主要的机制,没有中断,操作系统什么也干不了,没法输入没法输出,不能管理硬件资源,也不能向上层运用供应做事。而且操作系统本身就像是一个去世循环,等待事宜发生需求来临,然后为其供应做事办理问题。而这事宜的发生与处理便是靠中断机制来掌握的,以是说中断对付操作系统来说有着举足轻重的浸染,而我们也有必要理解中断,理清中断的过程。
喜好本文的朋友,欢迎关注"大众年夜众号 程序员小灰,收看更多精彩内容