linux softirq和tasklet的关系

书本上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。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值