中断基础
关于中断的概念,很多人还停留在书本上,我们结合实际的操作系统来理解。先给出硬中断和软中断的介绍:
硬中断:外设处理过程中产生的,通过硬件控制器通知cpu自己的状态变化。
软中断:硬中断应该很快完成,才能有快的响应,所以将一部分可以延迟的处理从硬中断里独立出来,当硬中断处理完之后再处理这部分,就是软中断。
下面,我们以linux为例,分析一下中断的嵌套情况。
硬中断的嵌套
《深入理解linux内核》中讲过,linux下的硬中断处理是可以嵌套的,并且没有优先级。也就是说,一个中断可以打断正在执行的中断(同种中断除外,后文会讲)。无优先级地支持硬中断嵌套有两个主要原因:短时间内接受更多的中断,可以有大的设备控制吞吐量;无优先级可以简化内核,提高移植性。
硬中断的具体linux实现流程是:(参考linux kernel 4.0)
硬中断的汇编处理->do_IRQ->handle_irq->handle_edge_irq(handle_level_irq)->handle_irq_event->具体设备的硬中断处理
同种中断不嵌套是通过设置该种中断的数据结构的IRQD_IRQ_INPROGRESS标志位来屏蔽(本cpu和其它cpu的同种中断)的,置位表示已经在处理该种中断了,同种中断会判断此标志而退出,同时置上IRQS_PENDING标志位表示此种中断还需继续处理。这个过程是不是很类似于软中断的防止嵌套的套路?我们(计算机学习微信公众号:jsj_xx)的理解是:它们本质是一样的,只是硬中断这里防的是同种类型(即使是不同cpu上),而软中断那里防的是所有类型(只在同一个cpu上,还记得软中断基于per-cpu的数据结构吧),但防范机制是一样的!
据此,我们可以推出硬中断的最大的嵌套层数是:硬中断的类型数(同时需要未设置IRQF_DISABLED标志位,马上讲到)。
2009年开源社区已经开始讨论默认设置IRQF_DISABLED标志位(http://lwn.net/Articles/321663/):如果设置了IRQF_DISABLED,那么该硬中断不允许被打断,也就禁止了嵌套。实际应用中,由于多队列网卡(一个网卡不再仅仅产生一种中断了,可能多达数十个!)会导致中断栈溢出,故于2010年终于关闭硬中断嵌套机制了,具体参考patch:e58aa3d2d0cc01ad8d6f7f640a0670433f794922(genirq: Run irqhandlers with interrupts disabled)
想想,有很多非常重要的事要做,是逐个做还是打断式并行做?如果是人去做的话,肯定会选逐个做。机器也一样?打断式并行做导致记录现场的存储量过大而崩溃。。。
硬中断的提速很重要,不管是拆分出软中断还是中断线程化,都是希望硬中断不要过多影响用户进程(特别是实时进程),毕竟有些硬中断和某些高优先级用户进程相比,其实并不重要。
软中断的嵌套
同种软中断不可以嵌套,但可以并行在不同cpu上,即使是同种类型。详细讲解请参考我们(计算机学习微信公众号:jsj_xx)之前的《理解linux内核的软中断(上/下)》。
总结
简洁地讲解硬中断和软中断的嵌套情况,硬中断的目标很明确:要快,不能影响系统其它高优先级进程。硬中断的详细细节(包括PIC/APIC/EDGE/LEVEL等)我们以后再讲。(纯属我们自己理解,如有不妥,还望指正)
关注我们(计算机学习微信公众号:jsj_xx),原创技术文章,感悟计算机,透彻理解计算机!