一、唠嗑
对应的源码在 kernel/softirq.c 。
softirq 里有很多的已定义的软中断处理。其中, tasklet只是其中的一个,在softirq_init中打开了 tasklet的中断
open_softirq(TASKLET_SOFTIRQ, tasklet_action);
也就是说,如果触发了TASKLET_SOFTIRQ这个软中断,tasklet_action就会被执行。
tasklet 用 tasklet_struct 来表示一个一个的小任务,并用 tasklet_init 来初始化(也可以用DECLARE_TASKLET
或 DECLARE_TASKLET_DISABLED)。并调用 tasklet_schedule 来调用对应的小任务。而tasklet_schedule 是通过触发
TASKLET_SOFTIRQ的软中断执行tasklet_action,在tasklet_action中才是真正的调用到小任务的。tasklet 是基于 softirq
的基础之上。
对 softirq 的思考,中断就是外来的一个信号触发一个动作。外来的中断如果是硬件中断就好理解了,如果是软件的,那就
是软中断了。软件就是直接调用 raise_softirq_irqoff 或者 raise_softirq 来触发对应的中断,相当于是硬件拉低一下电平。
二、API
对应的源码在 kernel/softirq.c 。
softirq 里有很多的已定义的软中断处理。其中, tasklet只是其中的一个,在softirq_init中打开了 tasklet的中断
open_softirq(TASKLET_SOFTIRQ, tasklet_action);
也就是说,如果触发了TASKLET_SOFTIRQ这个软中断,tasklet_action就会被执行。
tasklet 用 tasklet_struct 来表示一个一个的小任务,并用 tasklet_init 来初始化(也可以用DECLARE_TASKLET
或 DECLARE_TASKLET_DISABLED)。并调用 tasklet_schedule 来调用对应的小任务。而tasklet_schedule 是通过触发
TASKLET_SOFTIRQ的软中断执行tasklet_action,在tasklet_action中才是真正的调用到小任务的。tasklet 是基于 softirq
的基础之上。
对 softirq 的思考,中断就是外来的一个信号触发一个动作。外来的中断如果是硬件中断就好理解了,如果是软件的,那就
是软中断了。软件就是直接调用 raise_softirq_irqoff 或者 raise_softirq 来触发对应的中断,相当于是硬件拉低一下电平。
二、API
2.1 softirq
void __init softirq_init(void)
// 初始化
void open_softirq(int nr, void (*action)(struct softirq_action *))
// 打开一个软中断,为什么叫打开而不叫注册呢,因为softirq是已经预定义好了。
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
};
void raise_softirq(unsigned int nr)
// 触发软中断, 其中有关中断的操作
inline void raise_softirq_irqoff(unsigned int nr)
// 触发软中断,如果已经关中断了,那就调用这个 xxx_irqoff 就是这个意思
2.2 tasklet
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data)
DECLARE_TASKLET(name, func, data)
DECLARE_TASKLET_DISABLED(name, func, data)
// 初始化 tasklet
static inline void tasklet_schedule(struct tasklet_struct *t)
// 调用
static inline void tasklet_disable(struct tasklet_struct *t)
static inline void tasklet_enable(struct tasklet_struct *t)
// 使能操作
extern void tasklet_kill(struct tasklet_struct *t);
// 从内核中把该tasklet丢掉