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设备驱动程序)

时间延迟 如何度量时间差,比较时间 如何获得当前时间 如何将操作延迟指定的一段时间 如何调度异步函数到指定的时间之后执行 度量时间差 内核通过定时器中断来跟踪时间流。 时钟中断由...
  • s651665496
  • s651665496
  • 2016年04月25日 20:43
  • 1058

linux中的tasklet机制

转自: http://www.kerneltravel.net/?p=143 中断服务程序一般都是在中断请求关闭的条件下执行的,以避免嵌套而使中断控制复杂化。但是,中断是一个随机事件,它随时会到...
  • coder_jack
  • coder_jack
  • 2013年10月24日 15:50
  • 1284

把握linux内核设计思想(四):下半部机制之tasklet

【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】         tasklet是利用软中断实现的一种下半部机制。tasklet...
  • gentleliu
  • gentleliu
  • 2015年07月28日 23:46
  • 1521

【Linux开发】linux设备驱动归纳总结(一):内核的相关基础概念

linux设备驱动归纳总结(一):内核的相关基础概念 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
  • LG1259156776
  • LG1259156776
  • 2016年05月16日 11:55
  • 510

linux中设备驱动和设备文件

可能是以前的驱动太多简单,也可能是我看书的时候不够仔细,一直以为ko写好以后,insmod成功以后就能在/dev下直接引用。其实不然。 对于misc类型的驱动,可能确实如此(没有系统的考证过)。但是对...
  • hopshine
  • hopshine
  • 2014年02月17日 13:03
  • 1209

设备驱动----Linux中总线、设备、驱动是如何关联的?

对于Linux驱动开发来说,设备模型的理解是根本,顾名思义设备模型是关于设备的模型,设备的概念就是总线和与其相连的各种设备了。 电脑城的IT 工作者都会知道设备是通过总线连到计算机上的,而且还需要对...
  • yf210yf
  • yf210yf
  • 2013年06月30日 14:56
  • 3189

如何学好linux设备驱动

Linux系统目前主要维护2.4和2.6两个内核版本,在http://www.kernel.org/ 网站上已经可以下载到最新的2.6内核linux-2.6.38.6,及最新的2.4内核linux-2...
  • shuilaner_
  • shuilaner_
  • 2017年01月10日 16:32
  • 1239

Linux设备驱动模型

尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要。 Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个...
  • xiahouzuoxin
  • xiahouzuoxin
  • 2013年05月18日 14:11
  • 26075

Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用

关与设备树的概念,我们在Exynos4412 内核移植(六)—— 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用          Device Tree是一种描述硬件的数据结...
  • zqixiao_09
  • zqixiao_09
  • 2016年03月14日 20:47
  • 9940

第一个linux驱动_读写设备文件(2)

------在android模拟器和开发板上进行测试驱动模块 第一步添加逻辑功能部分代码 1.添加建立文件部分代码,添加后的hello.c的代码如下: #include #include #...
  • ddway12
  • ddway12
  • 2016年12月02日 20:17
  • 858
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux设备驱动下的tasklet
举报原因:
原因补充:

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