您的位置:首页 > 运维架构 > Linux

关于linux内核中断的个人总结

2011-11-12 23:32 211 查看
中断主要分为处理器自身的内部异常和外围设备的外部中断。异常必须与时钟同步,而中断随时可以发生。

对于异常,处理器自己会检测到,然后根据异常的类型跳到对应的中断处理程序去执行。

下面主要总结一下外部中断。

我先理一理中断处理的大概过程:

首先是外围硬件设备想请求处理器为自己做些事情的时候,就通过自己对应的IRQ线发出中断请求信号给处理器,告诉处理器这里有一个硬件中断请求处理器响应。处理判断自己可以处理请求的时候的时候,就通过查看这个中断是由那个IRQ线发送来的(然后判断自己是否可以响应这个IRQ上的中断)确定由那个中断处理程序来处理这个中断请求。然后进入中断上下文在这个中断处理程序中,调用这个发出这个中断的设备的驱动程序在内核中注册的用于处理这个中断请求的相关代码。

处于中断上下文的中断程序,只能被比自己优先级高的程序所中断,不可能被其他任何进程给中断,如果没有其他更高优先级的中断结束中断程序对当前CPU的占用的话,他会一直独占着CPU,除非自己主动让出。所以在中断上下文中不能调用任何可能导致休眠的函数。这也就是为什么要区分进程上下文和中断上下文两种环境了。他们一个可以被内核调度,一个不能。

好了。现在在梳理一下中断发生的详细过程。

首先,在设计硬件的时候,就要把自己的硬件的中断相关的引脚,通过硬件布线连接到中断控制器的特定的IRQ线上。中断控制器与其他设备相连的各条线叫做IRQ线,即中断请求线。什么类型使用那条IRQ线一般都是有的标准规定的。而这对设备发出的每一类中断,在设备的驱动程序中都要编写相关的中断处理代码,然后跟该类中断对应的IRQ线绑定,并注册到内核中,以方便内核在接受到相关IRQ上中断请求时候,能够判断应该调用那段代码来处理它。

然后当外围设备发生时间需要通知处理器(处理器有依靠内核来处理)来处理的时候就发一个中断给处理器。所谓中断。其实就是一个电信号。这个电信号并不是直接发给处理器的。它是先发送给中断控制器,然后再由中断控制器进行一些相关控制之后再交给处理器来处理。中断控制器在这里就是扮演了一个中间者,代理的角色。这可以看做是迪米特法则的运用:不要跟陌生人说话。这样就大大的减轻了处理器的负担。现在处理器只需要跟中断控制器一个人打交道,而不用跟那么多的中断直接交互了。

对于X86的中断控制器8259A,这个电信号是发送到中断控制器的IRQ线对应的IR引脚上的。当这个引脚上有电信号的时候,如果内核没有把这个IRQ线上的中断屏蔽的话,中断控制器会把这个IRQ中断请求记录在一个寄存器中(IRR寄存器,专门用于保存当前收到了那些中断请求,并且这些请求还没有提交给CPU),然后决定要不要用当的然后通过自己的INT引脚发送电信号给处理器的INTR引脚。这样处理器就知道有中断到来了。等处理判断自己可以处理中断请求了(每一条指令执行完了之后,CPU都会去检查INTR引脚是否有信号从而及时发现外部中断的到来,然后查看CPU是否允许中断---通过查看处理器自己的一个专门用于保存是否允许中断的寄存器EFLAGS来实现),就通过自己的一个引脚(X86为INTA引脚)来应答中断控制器(8259A),表示收到中断请求。然后8259A收到应答之后就知道处理器现在可以处理中断了,然后他就从IRR中记录的未处理中断中挑选出一个优先级最高的来交给处理器去处理(根据IRQ中断号,计算出他在内核中的中断向量值,然后根据这个值的大小,通过相关的数据线D0~D7来告诉处理中断向量的值应该是多少---当然了在这之前应该把这个IRQ在IRR中的位清零,因为毕竟它现在已经提交给CPU了)。

这上面8259A的处理中应该还有关于现在到来的中断和CPU当前正在执行的中断的优先级进行比较的工作。具体不太清楚。我猜想是比较当前当收到的这个中断的优先级和寄存器ISR保存的当前CPU正在处理的中断的优先级。然后决定要不要中断当前正在执行的另一个中断。如果决定不中断了,那么就不发送信号给CPU。然后CPU执行完中断之后,也必须得把8259A中断控制器中保存的当前正在执行的信息清零,然后8259A也同时执行发送一个信号给CPU的INTR引脚的操作。以便继续其他的中断。----------不过这段文字只是本人的猜测而已。

以上中断控制器部分是体系结构相关的。

然后接下来就是CPU和内核的事情。具体明天再继续总结吧。今天已经很晚了。要睡觉饿了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: