Linux中断下半部处理有三种方式:软中断、tasklet、工作队列。
  曾经有人问我为什么要分这几种,该怎么用。当时用书上的东西蒙混了过去,但是自己明白自己实际上是不懂的。近有时间了,于是试着整理一下linux的中断处理机制,目的是起码从原理上能够说得通。
  一、简单的中断机制
  简单的中断机制是像芯片手册上讲的那样,在中断向量表中填入跳转到对应处理函数的指令,然后在处理函数中实现需要的功能。类似下图:

  这种方式在原来的单片机课程中常常用到,一些简单的单片机系统也是这样用。
  它的好处很明显,简单,直接。
  二、下半部
  中断处理函数所作的第一件事情是什么?答案是屏蔽中断(或者是什么都不做,因为常常是如果不清除IF位,等于屏蔽中断了),当然只屏蔽同一种中断。之所以要屏蔽中断,是因为新的中断会再次调用中断处理函数,导致原来中断处理现场的破坏。即,破坏了 interrupt context。
  随着系统的不断复杂,中断处理函数要做的事情也越来越多,多到都来不及接收新的中断了。于是发生了中断丢失,这显然不行,于是产生了新的机制:分离中断接收与中断处理过程。中断接收在屏蔽中断的情况下完成;中断处理在时能中断的情况下完成,这部分被称为中断下半部。

  从上图中看,只看int0的处理。Func0为中断接收函数。中断只能简单的触发func0,而func0则能做更多的事情,它与funcA之间可以使用队列等缓存机制。当又有中断发生时,func0被触发,然后发送一个中断请求到缓存队列,然后让funcA去处理。
  由于func0做的事情是很简单的,所以不会影响int0的再次接收。而且在func0返回时会使能int0,因此funcA执行时间再长也不会影响int0的接收。
  三、软中断
  下面看看linux中断处理。作为一个操作系统显然不能任由每个中断都各自为政,统一管理是必须的。
  我们不可中断部分的共同部分放在函数do_IRQ中,需要添加中断处理函数时,通过request_irq实现。下半部放在do_softirq中,也是软中断,通过open_softirq添加对应的处理函数。

  四、tasklet
  旧事物跟不上历史的发展时,总会有新事物出现。
  随着中断数的不停增加,软中断不够用了,于是下半部又做了进化。
  软中断用轮询的方式处理。假如正好是后一种中断,则必须循环完所有的中断类型,才能终执行对应的处理函数。显然当年开发人员为了保证轮询的效率,于是限制中断个数为32个。
  为了提高中断处理数量,顺道改进处理效率,于是产生了tasklet机制。