其他分享
首页 > 其他分享> > 十、【工作队列】tasklet、上半部和下半部

十、【工作队列】tasklet、上半部和下半部

作者:互联网

一、概述

1、工作队列(workqueue)

2、Tasklet
Tasklet,同样,也是先接下任务,但不立刻做任务,与work很类似。tasklet运行在软中断上下文。

这三句话,是比较笼统的理解,现在回到linux具体来理解:

1)软中断触发时机:

不管是中断上下文,还是非中断上下文,最终都是调用__do_softirq实现的软中断,在这个函数里面是打开硬件中断,关闭内核抢占。这就是软中断上下文,即开硬件中断,关闭抢占。

(2)tasklet是基于软中断实现的,用在中断服务程序触发tasklet,则就是中断下半部分,也是用得最多的情况。用在进程上下文触发tasklet,则很类似workqueue,但是tasklet不能有睡眠(因为关闭抢占的,不考虑硬件中断,就是原子性的),也不适合做非常耗时的,如果是非常耗时的,尽量交给workqueue(可以在tasklet回调里面用work,把更耗时,时间要求更不高的,交给workqueue)。

3、中断上半部和下半部

  由于中断随时可能发生,所以必须保证中断处理程序可以快速执行;但是中断处理程序可能又会处理大量的任务,两者之间存在矛盾,所以一般会把中断处理的过程分成两部分:上半部和下半部。

  对于网卡的中断处理,上半部会执行通知硬件、拷贝网络数据报到内存并继续读取新数据包,这些重要、紧急且与硬件相关的工作,因为网卡接收的网络数据包的缓存大小通常是固定的、有限的,一旦被延迟可能造成缓存溢出。而数据包的处理等操作,则由下半部来完成。

二、tasklet的接口函数

1、定义一个tasklet

#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

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

参数:

2、tasklet小任务的处理函数

void key_tasklet_func(unsigned long data)//下半部
{
//做一些对时间要求不严格的工作

}

3、调度tasklet

static inline void tasklet_schedule(struct tasklet_struct *t)

二、使用tasklet实例 

  在按键中断处理程序中,我们将键值的获取归为比较紧急的任务(上半部),对于时间要求比较严格。对于等待队列的唤醒归为可以稍微退后执行的工作,所以归为下半部。

下半部我们用tasklet来实现。

相关链接Linux中断原理、上半部和下半部、硬中断和软中断

标签:struct,队列,中断,半部,workqueue,上半部,tasklet,上下文
来源: https://www.cnblogs.com/yuanqiangfei/p/15707993.html