一直以来对linux中断有些疑问,今天在网上看到这个讨论,特此记录,以备查验:
查看了以下文章:
http://blog.csdn.net/adaptiver/article/details/6834337
正在看关于linux中断的有关问题。
1 允许中断嵌套,是否会丢失中断? 如果丢失有什么后果?
一般申请中断的时候都允许开中断,即不使用SA_INTERRUPT标志。如果允许共享则加上 SA_SHIRQ,如果可以为内核熵池提供熵值(譬如你写的驱动是ide之类的驱动),则再加上 SA_SAMPLE_RANDOM标志。这是普通的中断请求过程。对于这种一般情况,只要发生中断,就可以抢占内核,即使内核正在执行其他中断函数。这里有两点说明:一是因为linux不支持 中断优先级,因此任何中断都可以抢占其他中断,但是同种类型的中断(即定义使用同一个 中断线的中断)不会发生抢占,他们会在执行本类型中断的时候依次被调用执行。二是所谓 “只要发生中断,就可以抢占内核”这句是有一定限制的,因为当中断发生的时候系统由中断门 进入时自动关中断(对于x86平台就是将eflags寄存器的if位置为0),只有当中断函数被执行 (handle_IRQ_event)的过程中开中断之后才能有抢占。 对于同种类型的中断,由于其使用同样的idt表项,通过其状态标志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同种类型的中断函数执行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函数被重入),对于不同的中断,则可以自由的嵌套。因此,所谓中断嵌套, 对于不同的中断是可以自由嵌套的,而对于同种类型的中断,是不可以嵌套执行的。
以下简单解释一下如何利用状态标志来防止同种类型中断的重入:
当某种类型的中断第一次发生时,首先其idt表项的状态位上被赋予IRQ_PENDING标志,表示有待处理。 然后将中断处理函数action置为null,然后由于其状态没有IRQ_INPROGRESS标志(第一次),故将其状态置上IRQ_INPROGRESS并去处IRQ_PENDING标志,同时将action赋予相应的中断处理函数指针(这里是一个重点,linux很巧妙的用法,随后说明)。这样,后面就可以顺利执行handle_IRQ_event进行中断处理,当在handle_IRQ_event中开中断后,如果有同种类型的中断发生,则再次进入do_IRQ函数,然后其状态位上加上IRQ_PENDING标志,但是由于前一次中断处理中加上的IRQ_INPROGRESS没有被清除,因此这里无法清除IRQ_PENDING标志,因此action还是为null,这样就无法再次执行handle_IRQ_event函数。从而退出本次中断处理,返回上一次的中断处理函数中,即继续执行handle_IRQ_event函数。当handle_IRQ_event返回时检查IRQ_PENDING标志,发现存在这个标志,说明handle_IRQ_event执行过程中被中断过,存在未处理的同类中断,因此再次循环执行handle_IRQ_event函数。直到不存在IRQ_PENDING标志为止。
2 linux 关中断期间来的中断会否丢失? 如果丢失有什么后果?
以8259A为例:中断来了, IRQ 线边缘触发, ESR 如果是 reset 状态, 则锁存, 要么已经处于锁存状态; 最终结果就是无论如何, 这个信号不会丢失;既然不会丢失, 则无论什么时候开启中断, 都会最终发送到 CPU, 最坏的结果是,期间有多个中断到来,则多个中断合并成一个而已, 而这个很显然不是问题;
3 既然关中断不会丢失中断,但是对于期间到来的多个中断会合并成一个,即只处理一次;时钟中断中需要更新jieffis计数值,如果多个中断合成一个,是否影响jieffis值得准确性?
哈哈,别当心,Linux不会把你的时间给高错的,如果这个问题都不能解决,还有人用吗?
其实在Linux中还有一个全局变量用于修正jieffis的值。
一般在一个计算机系统中存在三个时间发生器,一个用于记录日期时间的,它就是利用电池进行供电的一个单独芯片——RTC,第二个是PIT(可编程间隔定时器),第三个是TSC时间戳计数器。
而PIT就是产生IRQ0的定时器芯片。而进行校正的就是利用TSC计数器,它在每个clock-cycle就会自动加一,不需要CPU操作,所以每个时钟中断产生时都可以利用一个全局变量记录下TSC的值,在下次时钟中断时再用这个全局变量校正jieffis的值,这样就可以记录精准的时间。(TSC计数器是纳秒级的。)
阅读(1981) | 评论(0) | 转发(0) |