android底层驱动学习之工作队列work_queue相关参数

本文介绍了Android底层驱动中的工作队列work_queue,包括其概念、数据结构、创建与执行工作、与tasklet的区别,并提供了选择工作队列或tasklet的指导原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android底层驱动学习之工作队列work_queue相关参数

 

今早看了与工作队列有关的相关知识,下面总结下:

1.       什么是工作队列:

工作队列(work queue)是另外一种将工作推后执行的形式。工作队列可以把工作推后,交由一个内核线程去执行—这个下半部分总是会在进程上下文执行,但由于是内核线程,其不能访问用户空间。最重要特点的就是工作队列允许重新调度甚至是睡眠。

实际上,工作队列的本质就是将工作交给内核线程处理,因此其可以用内核线程替换。但是内核线程的创建和销毁对编程者的要求较高,而工作队列实现了内核线程的封装,不易出错,所以我们也推荐使用工作队列。

工作队列和tasklet都是可以将工作推后的形式

 

2.首先是不是要先来看下工作队列的数据结构,如下:

l  struct work_struct //一个工作的结构体

{

      atomic_long_tdata;//工作处理函数的参数

      structlist_head entry;

      work_func_tfunc;//工作处理函数

#ifdef CONFIG_LOCKDEP

      structlockdep_map lockdep_map;

#endif

};

l  struct workqueue_struct //一个工作队列

{

 struct cpu_workqueue_struct *cpu_wq;//创建对应的cpuworkqueue,叫做工作者线程

 struct list_head list;

 const char *name;   /*workqueue name*/

 int singlethread;   /*是不是单线程 - 单线程我们首选第一个CPU-0表示采用默认的工作者线程event*/

 int freezeable;  /* Freeze threads during suspend */

 int rt;

};

 

3.那么如何去创建和执行一个工作呢?

首先创建一个工作,有静态和动态两种方法:

l  静态:

DECLARE_WORK(name,function);//定义正常执行的工作项

DECLARE_DELAYED_WORK(name,function);//定义延后执行的工作项

l  动态:

INIT_WORK(&data->touch_event_work,fts_touch_irq_work)

INIT_DELAYED_WORK(&led_work,s0340_ledtime_scanf);

 

4.接下来就是创建工作队列了

l  create_singlethread_workqueue("fts_wq")

用于创建workqueue,只创建一个内核线程。

l  create_workqueue("fts_wq")

用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。

 

5.将创建好的工作加入到工作队列中并执行

l  queue_work(fts_ts->ts_workqueue,&fts_ts->touch_event_work);

调度执行一个指定workqueue中的任务

l  queue_delayed_work

延迟调度执行一个指定workqueue中的任务,功能与queue_work类似,输入参数多了一个delay。

 

6.也可以单独执行一个工作: 

l  schedule_work(&fts_ts->touch_event_work)

调度执行一个具体的任务,执行的任务将会被挂入Linux系统提供的workqueue——keventd_wq

l  schedule_delayed_work

延迟一定时间去执行一个具体的任务,功能与schedule_work类似,多了一个延迟时间

 

 

那你是不是会有一个问题:工作队列和tasklet有什么区别,二者都是可以处理进程上下文的?

答:Linux2.6内核使用了不少工作队列来处理任务,他在使用上和 tasklet最大的不同是工作队列的函数可以使用休眠,而tasklet的函数是不允许使用休眠的。

 

另外,内核必须挂载文件系统才可以使用工作队列。我的理解是:工作队列也属于调度,如果内核挂了,他就不调度了,当然就不能用工作队列了。

工作队列的使用又分两种情况,一种是利用系统共享的工作队列来添加自己的工作,这种情况处理函数不能消耗太多时间,这样会影响共享队列中其他任务的处理;另外一种是创建自己的工作队列并添加工作。

Tasklet其实和软中断很像,首先通过在驱动初始化时做tasklet_init注册tasklet,然后在中断处理程序结束前调用tasklet_schedule来使能tasklet。

 

那么最后如何选择这两种都可以推后的形式呢?

 

l  如果推后执行的任务需要睡眠,那么只能选择工作队列;

l  如果推后执行的任务需要延时指定的时间再触发,那么使用工作队列,因为其可以利用timer延时;

l  如果推后执行的任务需要在一个tick之内处理,则使用软中断或tasklet,因为其可以抢占普通进程和内核线程;

l  如果推后执行的任务对延迟的时间没有任何要求,则使用工作队列,此时通常为无关紧要的任务。

实际上,工作队列的本质就是将工作交给内核线程处理,因此其可以用内核线程替换。但是内核线程的创建和销毁对编程者的要求较高,而工作队列实现了内核线程的封装,不易出错,所以我们也推荐使用工作队列。

 

PS: ,linux调度是以进程(或者说线程)来的,即做调度是不同进程上下文的切换.

7,而可以看到软中断逻辑不属于任何进程,所以才不能睡眠,因为一旦睡眠,cpu切换出去,就切不回来了(和6一起理解).并不是说无法做到在软/硬中断睡眠,只是目前Linux的实现就是这样的,不允许你这么做,要是这么做了,你就等死.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值