目前支持的三种下半部机制:软中断(与前面系统调用部分的软中断不是一个概念),tasklet, 工作队列。
软中断:由softirq_action结构表示,定义在linux/interrupt.h中,kernel/softirq.c中定义了32个该结构的数组,目前只使用6个
softirq_action结构中有个action字段,和data字段,分别是待执行的函数和传给该函数的参数,但函数的参数类型是
softirq_action结构的指针,也就是当要使用data参数时是直接将当前对应的整个softirq_action结构的指针传入的,这个技巧是为
了当softirq_action结构发生变化时无需时所有的执行函数的代码都改变。
软中断必需要标记后才会触发,一般中断处理程序都回触发他的软中断,使其稍后执行,以下情况待处理的软中断会被检查,处理:
处理完一个硬件中断后
在ksoftirqd内核线程中
在那些显式检查和执行待处理的软中断的代码中,如网络子系统中。
无论什么办法,软中断都要在do_softirq中执行,具体做的:P71
软中断的添加方法以及触发方法:P72
软中断程序执行时允许响应中断,但不能休眠,一个处理程序运行时,当前处理器上的软中断被禁止,但其他的处理器啊是可以执行
别的软中断,注意一个软中断执行时的同时会再次被触发,也就是被其他的处理器运行,所以软中断使用的全局变量等结构必须上锁
或是使用单处理器数据(只属于一个处理器的数据)来避免锁,这也是推荐使用tasklet来处理的原因。
tasklet:使用较为常见,使用软中断来实现,tasklet在软中断中有两类HI_SOFTIRQ 和 TASKLWT_SOFTIRQ,前者优先级更高。
tasklet_struct结构(linux/interrupt.h):P74。
已调度的tasklet(等同于被触发的软中断)保存在tasklet_vec和tasklet_hi_vec(优先级比前者高)中。
调度tasklet:P74
do_softirq->task_action(TASKLWT_SOFTIRQ的处理程序)->处理tasklet_vec->使用tasklet_schedule进行调度
或->task_hi_action(HI_SOFTIRQ的处理程序)->处理tasklet_hig_vec->使用tasklet_hi_schedule进行调度:P74
软中断重新触发时的处理:P78
工作队列:使用内核线程去处理,区别是如果要休眠则使用工作队列(开销大),如果不需要休眠则使用tasklet:P80
struct workqueue_struct{
struct cpu_workqueue_struct cpu_wq[NR_CPUS];
}
里面数组的每一项表示一个工作者线程,且每一项对应一个CPU。