Linux2.6的软中断框架与2.4相比有了一些不同:2.2之前的传统bottom half已经几乎没有了,任务队列被取消,软中断的调用时机也有所不同。下面分析一下2.6软中断的框架。
2.6中软中断还是由函数do_softirq调用,但异常和系统调用返回、调度时不再执行软中断,执行时机变为以下3个:
l 硬件处理完一个中断之后(irq_exit函数)
l 内核线程ksoftirqd
l 显式调用do_softirq的地方(比如net子系统中)
do_softirq会遍历所有的softirq_vec,依次调用其中的action函数。系统预定义的软中断有:
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ, // 网络发送底半部(网卡中不一定要使用,2.6中也可以用work queue),NAPI中用到。
NET_RX_SOFTIRQ, // 网络接收底半部
BLOCK_SOFTIRQ, // block子系统专用软中断
TASKLET_SOFTIRQ, // 公共的tasklet使用
SCHED_SOFTIRQ,
#ifdef CONFIG_HIGH_RES_TIMERS
HRTIMER_SOFTIRQ,
#endif
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
};
l TASKLET_SOFTIRQ: tasklet_schedule函数实现了公共的tasklet机制,这个函数内部所做的就是把一个tasklet挂到CPU的tasklet链表,然后标记TASKLET_SOFTIRQ软中断。
l HI_SOFTIRQ : tasklet_hi_schedule函数实现另一个tasklet队列实例,这个函数内部是把tasklet挂到CPU的索引为tasklet_hi_vec的软中断链表,然后标记软中断。处理方式与TASKLET_SOFTIRQ相同。
l TIMER_SOFTIRQ: 实现定时器操作,内核中的msleep函数由这个软中断实现(注意这里实现的是msleep,不是udelay和mdelay)。另外内核定时器也通过此软中断实现。
l HRTIMER_SOFTIRQ: 高精度时钟,实现itimers,POSIX timers,nanosleep,precise in-kernel timing.
l SCHED_SOFTIRQ: 用于CPU的load balance
软中断不能嵌套,也不能在硬中断服务程序中执行,但多个软中断能在多个CPU上并发。
由于软中断的调用时机中,有一个是处理完硬件中断之后,实现中断的底半部机制。所以软中断中不能阻塞。