linux中断管理—软中断
一、简介
软中断是linux预留给系统中对时间要求最为严苛和最重要的中断下半部使用的。并且,驱动中只有一些对时间极其敏感的模块使用了。例如:块设备和网络子系统。linux系统中定义了几种软中断类型。如下所示(/include/interrupt.h):
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */
NR_SOFTIRQS
};
如果不需要真正高频率的线程任务调度,请避免分配新的软中断。意味着,linux内核不希望开发者新去扩充软中断类型,可以使用tasklet
来替代。
在linux内核中,定义了一个数组softirq_vec[]
来描述软中断。类似硬件中断描述数组irq_desc[]
。
如下定义(/kernel/softirq.c):
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
其中每个数组的元素为struct softirq_action
类型。对于linux来说,系统中的10软中断则一一对应10个softirq_action
。如下定义(/include/linux/interrupt.h):
struct softirq_action
{
void (*action)(struct softirq_action *);
};
二、软中断相关API总结
(2-1)注册软中断
通过调用open_softirq()
函数接口可以注册一个软中断。如下定义(/kernel/softirq.c):
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}
- nr :软中断的序号。
该函数较为简单,且没有过多的保护机制。可见,softirq_vec
数组是一个多CPU共享的数组。因系统在启动时是串行运行的,对于软中断的初始化过程,不会产生冲突。
(2-2)主动触发一个软中断
通过使用raise_softirq()
函数可以主动触发一个软中断。定义定义(/kernel/softirq.c):
void raise_softirq(unsigned int nr)
{
unsigned long flags;
local_irq_save(flags);
raise_softirq_irqoff(nr);
local_irq_restore(flags);
}
还可以使用raise_softirq_irqoff()
函数触发。但是该函数运行在关闭本地中断的情况下(意味着该函数可以在进程上下文
调用),如下定义(/kernel/softirq.c):
/*
* This function must run with irqs disabled!
*/
inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr);
if (!in_interrupt())
wakeup_softirqd();
}