linux系统中的中断上下部(top half、bottom half)

问题:linux系统中对中断的处理为什么会有上下部之分呢?这得从linux中中断的特性说起:

中断处理程序处于中断上下文,而中断上下文是不参与调度的,这样中断上下文不能出现可能休眠的操作,因为中断上下文一旦休眠就会交出cpu,而中断上下文不参与调度,也就是交出cpu时不会保存上下文,这样一旦交出cpu就永远不会回来了。这也就决定了在中断中不能和用户空间进行数据交互,因为这种交互可能会引起休眠。

还有一点,为了尽量提高系统的响应速度,中断程序运行的时间应该尽可能短。比如说中断来临后系统在处理中断服务程序,此时有一个事件发生,如果这个事件的优先级没有此时的中断优先级高,这个事件就会等待中断处理完成,而中断处理的时间越长,该事件等待的时间就越长,因为中断是不能被调度的,这样就会导致事件的响应速度很差,也就是响应性能不好。

出于对以上的考虑,linux操作系统才实现了中断的上下文。中断上下文具体有两种实现方式:一是tasklet(小任务),一是workqueue(工作队列)的方式。tasklet上下半部全部工作在中断上下文,在执行完上半部后不会立即执行下半部,此时的空隙可以被系统调度,但一旦执行了下半部就不能被调度了;workqueue的上半部工作在中断上下文,下半部工作在进程上下文,进程上下文是可以被调度的。这样这两种机制就可以解决上面的响应性问题。

问题:我们在看linux中驱动的实现时对中断的处理有时候没有用到中断的上下文,有时候是通过tasklet实现的中断上下文,有时候是通过workqueue实现的中断上下文,而我们中断上下部处理的原则又是什么呢?

必须立即进行的紧急处理的极少数任务应该放在中断的上半部中,此时是屏蔽了与自己同类型的中断的,任务量少,可以迅速的完成紧急任务。

需要较少时间的中等数量的急迫任务放在tasklet的下半部,tasklet的下半部工作在中断上下文,不会被调度,但是其不会屏蔽任何中断(包括与自己上半部同类型的中断),所以并不影响其他上半部对紧急任务的处理,同时自己不会被调度也能保证自己的急迫任务被迅速完成。

需要较多时间且不急迫的大量任务放在workqueue的下半部,workqueue的下半部工作在进程上下文,参与调度。其调度优先级比较高,操作系统会尽量先完成其任务,但是当其任务时间太长,操作系统也会调度去执行其他的用户进程,从而保证其他用户进程不至于死掉

总结:可能引起休眠的任务放在workqueue的下半部,因为其他的都工作在中断上下文,是不能被休眠的;在需要获得大量内存时、需要获取信号量时、阻塞操作时放在workqueue的下半部,因为获取大量内存时、获取信号量与阻塞操作时都可能会引起休眠。

展开阅读全文

没有更多推荐了,返回首页