linux设备驱动下的tasklet

原创 2012年03月29日 18:47:30

        在设备驱动的中断处理中经常会用到tasklet,在前面稍微看了下linux的软中断后,tasklet就很容易理解了。Tasklet也要用到软中断,而tasklet的用法和定时器的用法很相似。

         

         同样的在main.c中,

         start_kernel-->softirq_init

         先给出tasklet的结构体定义:

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

struct tasklet_head
{
	struct tasklet_struct *head;
	struct tasklet_struct **tail;
};

static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);

void __init softirq_init(void)
{
	int cpu;

	for_each_possible_cpu(cpu) {
		int i;

		per_cpu(tasklet_vec, cpu).tail =
			&per_cpu(tasklet_vec, cpu).head;
		per_cpu(tasklet_hi_vec, cpu).tail =
			&per_cpu(tasklet_hi_vec, cpu).head;
		for (i = 0; i < NR_SOFTIRQS; i++)
			INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
	}

	register_hotcpu_notifier(&remote_softirq_cpu_notifier);

	open_softirq(TASKLET_SOFTIRQ, tasklet_action);
	open_softirq(HI_SOFTIRQ, tasklet_hi_action);
}

这样在softirq_init函数中,首先初始化tasklet_vec

然后注册tasklet软中断,中断服务程序是tasklet_action

 

软中断的执行还是由ksoftirqd内核线程来处理。

 

下面看下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;
}


 

Tasklet的调度:

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

void __tasklet_schedule(struct tasklet_struct *t)
{
	unsigned long flags;

	local_irq_save(flags);
	t->next = NULL;
	*__get_cpu_var(tasklet_vec).tail = t;
	__get_cpu_var(tasklet_vec).tail = &(t->next);
	raise_softirq_irqoff(TASKLET_SOFTIRQ);
	local_irq_restore(flags);
}


 

这里先将刚才初始化的tasklet_struct加入这个tasklet_vec向量表中

这里调用raise_softirq_irqoff(TASKLET_SOFTIRQ);

来触发软中断。

 

那么,前面的中断服务程序是tasklet_action就开始执行了:

static void tasklet_action(struct softirq_action *a)
{
	struct tasklet_struct *list;

	local_irq_disable();
	list = __get_cpu_var(tasklet_vec).head;
	__get_cpu_var(tasklet_vec).head = NULL;
	__get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
	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 = NULL;
		*__get_cpu_var(tasklet_vec).tail = t;
		__get_cpu_var(tasklet_vec).tail = &(t->next);
		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
		local_irq_enable();
	}
}


 

遍历tasklet_vec向量表,调用每个tasklet中在注册时的t->func(t->data);函数。

 

 

这样,tasklet就可以用于中断的顶半部和底半部。

在中断处理的顶半部,调用tasklet_schedule函数

Tasklet关联的tasklet处理函数就是中断的底半部处理。

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

linux设备驱动归纳总结(六):3.中断下半部之tasklet

转自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet x...

Linux设备驱动四 (3)中断下半部分tasklet

先看一下如何使用tasklet,用完之后再看内核中是如何实现的: 步骤一、编写tasklet处理函数,定义并初始化结构体tasklet_struct: 内核中是通过tasklet_struct来维...

linux设备驱动编写_tasklet机制

在编写设备驱动时, tasklet 机制是一种比较常见的机制,通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成软中断完成。 ...

linux设备驱动编写_tasklet机制

时间过长而导致中断丢失,有时候我们需要把一些在中断处理中不是非常紧急的任务放在后面执行,而让中断处理程序尽快返回。在老版本的 linux 中通常将中断处理分为 top half handler 、 b...

linux设备驱动归纳总结(六):3.中断下半部之tasklet

CU首页 ┊ fh265>>博客 微博 相册 个人中心 好友 消息 [退出] ┊ 随便看看   博文 博主 相册  投票 活...
  • fh400
  • fh400
  • 2011-11-02 17:39
  • 1372

linux设备驱动归纳总结(六):3.中断下半部之tasklet

linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...

高级字符设备驱动--中断下半部机制之tasklet(一)

综述  Linux把中断处理例程分两部分: 上半分:实际响应中断的例程。 下半分:被顶部分调用,通过开中断的方式进行。 两种机制实现: Tasklet 工作队列work que...

字符设备驱动之Buttons-中断上下部(tasklet)

buttons.c #include #include #include #include #include #include #include #i...

【Linux设备驱动程序(第三版)】----tasklet

【Linux设备驱动程序(第三版)】----taskletjit.c#include #include #include #include #include #include ...

linux设备驱动模型七之driver

上节我们分析设备驱动模型中的device,主要是drivers/base/core.c,可以说是代码量最大的一个文件。本节要分析的驱动driver,就要相对简单很多。原因也很简单,对于driver,我...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)