linux softirq和tasklet的关系

来源:互联网 发布:我的校园软件 编辑:程序博客网 时间:2024/06/14 20:46
书本上tasklet就是基于softirq来实现的,下面的就从代码看看他们是怎么实现的。首先搞清楚softirq是怎么一回事,linux内核里面定义这几种softirq(可能内核版本不同,定义不同)
enum{HI_SOFTIRQ=0,TIMER_SOFTIRQ,NET_TX_SOFTIRQ,NET_RX_SOFTIRQ,SCSI_SOFTIRQ,TASKLET_SOFTIRQ};

然后在看看怎么去注册一个softirq

void open_softirq(int nr, void (*action)(struct softirq_action*), void *data){softirq_vec[nr].data = data;softirq_vec[nr].action = action;}


 


其中的action就是softirq的handler,那么我们再看看内核启动的过程中已经注册哪些softirq(目前只关注tasklet基于的HI_SOFTIRQ,TASKLET_SOFTIRQ)

void __init softirq_init(void){open_softirq(TASKLET_SOFTIRQ, tasklet_action, NULL);open_softirq(HI_SOFTIRQ, tasklet_hi_action, NULL);}

这里很明显地看到,内核注册了TASKLET_SOFTIRQ和HI_SOFTIRQ这两个类型的softirq,而其对于的handler分别是tasklet_action,tasklet_hi_action。其实tasklet的实现就关键这两个handler里面,那么我就进入其中一个看看

static void tasklet_action(struct softirq_action *a){struct tasklet_struct *list;local_irq_disable();list = __get_cpu_var(tasklet_vec).list;__get_cpu_var(tasklet_vec).list = NULL;local_irq_enable();while (list) {struct tasklet_struct *t = list;list = list->next;if (tasklet_trylock(t)) {if (!atomic_read(&t->count)) {if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))BUG();t->func(t->data);tasklet_unlock(t);continue;}tasklet_unlock(t);}local_irq_disable();t->next = __get_cpu_var(tasklet_vec).list;__get_cpu_var(tasklet_vec).list = t;__raise_softirq_irqoff(TASKLET_SOFTIRQ);local_irq_enable();}}

从代码可以看出,这个handler关键获取list = __get_cpu_var(tasklet_vec).list; 然后就执行里面的的函数,而这个链表就是tasklet的链表。那么我先看看tasklet又是怎么被注册的,也就是怎么插入这个链表。

void tasklet_init(struct tasklet_struct *t,  void (*func)(unsigned long), unsigned long data){t->next = NULL;t->state = 0;atomic_set(&t->count, 0);t->func = func;t->data = data;}


 

struct tasklet_struct{struct tasklet_struct *next;unsigned long state;atomic_t count;void (*func)(unsigned long);unsigned long data;};


 

static inline void tasklet_schedule(struct tasklet_struct *t){if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))__tasklet_schedule(t);}


 

void fastcall __tasklet_schedule(struct tasklet_struct *t){unsigned long flags;local_irq_save(flags);t->next = __get_cpu_var(tasklet_vec).list;__get_cpu_var(tasklet_vec).list = t;raise_softirq_irqoff(TASKLET_SOFTIRQ);local_irq_restore(flags);}

上面几条函数分别初始化和注册一个tasklet,而注册一个tasklet就是把tasklet对于的结构体插入链表里。

总的来说,就是注册一个softirq,然后在这个softirq的handler里面找到tasklet链表,然后再执行相应的函数,严格来说这里是注册两个softirq,因为有两个不同类型的tasklet。所以说tasklet的实现就是基于softirq。

 

原创粉丝点击