Workqueue机制中定义了两个重要的数据结构,分析如下:

cpu_workqueue_struct结构。该结构将CPU和内核线程进行了绑定。在创建workqueue的过程中,Linux根据当前系统CPU的个数创建cpu_workqueue_struct。在该结构主要维护了一个任务队列,以及内核线程需要睡眠的等待队列,另外还维护了一个任务上下文,即task_struct。

work_struct结构是对任务的抽象。在该结构中需要维护具体的任务方法,需要处理的数据,以及任务处理的时间。该结构定义如下:

struct work_struct {

unsigned long pending;

struct list_head entry;                 /* 将任务挂载到queue的挂载点 */

void (*func)(void *);                   /* 任务方法 */

void *data;                             /*任务处理的数据*

void *wq_data;                          /*work的属主 */

strut timer_list timer;                 /* 任务延时处理定时器 */

};

当用户调用workqueue的初始化接口create_workqueue或者create_singlethread_workqueue对workqueue队列进行初始化时,内核就开始为用户分配一个workqueue对象,并且将其链到一个全局的workqueue队列中。然后Linux根据当前CPU的情况,为workqueue对象分配与CPU个数相同的cpu_workqueue_struct对象,每个cpu_workqueue_struct对象都会存在一条任务队列。紧接着,Linux为每个cpu_workqueue_struct对象分配一个内核thread,即内核daemon去处理每个队列中的任务。至此,用户调用初始化接口将workqueue初始化完毕,返回workqueue的指针。

在初始化workqueue过程中,内核需要初始化内核线程,注册的内核线程工作比较简单,就是不断的扫描对应cpu_workqueue_struct中的任务队列,从中获取一个有效任务,然后执行该任务。所以如果任务队列为空,那么内核daemon就在cpu_workqueue_struct中的等待队列上睡眠,直到有人唤醒daemon去处理任务队列。

Workqueue初始化完毕之后,将任务运行的上下文环境构建起来了,但是具体还没有可执行的任务,所以,需要定义具体的work_struct对象。然后将work_struct加入到任务队列中,Linux会唤醒daemon去处理任务。

上述描述的workqueue内核实现原理可以描述如下:

      

在Workqueue机制中,提供了一个系统默认的workqueue队列——keventd_wq,这个队列是Linux系统在初始化的时候就创建的。用户可以直接初始化一个work_struct对象,然后在该队列中进行调度,使用更加方便。

Workqueue编程接口

序号

接口函数

说明

1

create_workqueue

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

@name:workqueue的名称

2

create_singlethread_workqueue

用于创建workqueue,只创建一个内核线程。输入参数:

@name:workqueue名称

3

destroy_workqueue

释放workqueue队列。输入参数:

@ workqueue_struct:需要释放的workqueue队列指针

4

schedule_work

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

@ work_struct:具体任务对象指针

5

schedule_delayed_work

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

@work_struct:具体任务对象指针

@delay:延迟时间

6

queue_work

调度执行一个指定workqueue中的任务。输入参数:

@ workqueue_struct:指定的workqueue指针

@work_struct:具体任务对象指针

7

queue_delayed_work

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

work queue 的使用实例:

 

struct my_work_t {

char *name;

struct work_struct work;  //作为自己数据结构的成员,然后用container_of获得my_work_t的指针

};
void my_func(struct work_struct *work)

{

struct my_work_t *my_work = container_of (work, struct my_work_t, work);

printk(KERN_INFO “Hello world, my name is %s!/n”, my_work->name);

}
struct workqueue_struct *my_wq = create_workqueue(“my wq”);      //创建自己的work queue

struct my_work_t my_work;

my_work.name = “Jack”;

INIT_WORK(&(my_work.work), my_func);          //初始化自己的work queue

queue_work(my_wq, &(my_work.work));

destroy_workqueue(my_wq);                     //销毁自己的work queue

Workqueue机制的实现的更多相关文章

  1. Linux kernel workqueue机制分析

    Linux kernel workqueue机制分析 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.10.108的workqueue文档分析其基 ...

  2. Linux kernel workqueue机制分析【转】

    转自:http://www.linuxsir.org/linuxjcjs/15346.html 在内核编程中,workqueue机制是最常用的异步处理方式.本文主要基于linux kernel 3.1 ...

  3. workqueue机制分析之process_one_work分析

    工作者线程不断执行,从work_poll结构中卸下一个work, 然后进入函数process_one_work 来执行这个work. process_one_work(struct worker *w ...

  4. Linux内核中的Workqueue机制分析

    1. 什么是workqueue Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的.通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线 ...

  5. workqueue机制分析之wb_workfn函数

    上面一篇文章说到: process_one_work中最重要的一件事情就是worker->current_func(work); 这里就具体到一项很具体的任务了,由于我要研究文件系统嘛,所以很自 ...

  6. Linux workqueue疑问【转】

    转自:http://blog.csdn.net/angle_birds/article/details/9387365 各位大神,你们好.我在使用workqueue的过程中遇到一个问题. 项目采用uC ...

  7. Linux workqueue工作原理 【转】

    转自:http://blog.chinaunix.net/uid-21977330-id-3754719.html 转自:http://bgutech.blog.163.com/blog/static ...

  8. workqueue --最清晰的讲解【转】

    转自:https://www.cnblogs.com/zxc2man/p/6604290.html 带你入门: 1.INIT_WORK(struct work_struct *work, void ( ...

  9. Linux中断管理 (3)workqueue工作队列

    目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...

随机推荐

  1. javascript+html5+css3下拉刷新 数据效果

    文章摘自:suchso.com/projecteactual/javascript-html5-css3-taobao-xiala-data.html segmentfault.com/a/11900 ...

  2. 第153天:关于HTML标签嵌套的问题详解

    HTML标签 1.块级元素 div.h1~h6.address.blockquote.center.dir.dl.dt.dd.fieldset.form.hr.isindex.menu.noframe ...

  3. MySQL5.7 初使用

    MySQL 5.7.6 发布了快一年了, 官方的说法是比起前几代有很大的安全性提升,性能报告也是比之前版本提升了 2.3倍. 性能上这么大的提升,安全上也这么大的改进,怎么能不心动呢,这几天出于好奇, ...

  4. 使用android资源

    1.我们可以命名的资源种类有多少? 答: res/anim/ XML文件,它们被编译进逐帧动画(frame by frame animation)或补间动画(tweened animation)对象 ...

  5. 转:pairwise 代码参考

    Learning to rank with scikit-learn: the pairwise transform http://fa.bianp.net/blog/2012/learning-to ...

  6. 【BZOJ4198】【NOI2015】荷马史诗(贪心,Huffman树)

    [BZOJ4198][NOI2015]荷马史诗(贪心,Huffman树) 题面 BZOJ 洛谷 题解 合并果子都是不知道多久以前做过的了.现在才知道原来本质就是一棵哈夫曼树啊. 这题我们仔细研究一下题 ...

  7. SCWS中文分词,安装说明(以:Win32环境、utf8字符集为例)

    SCWS官方网站:http://www.xunsearch.com/scws/ 1. 根据您当前用的 PHP 版本,下载相应已编译好的 php_scws.dll 扩展库.    目前支持 PHP-5. ...

  8. Codeforces 601D. Acyclic Organic Compounds(四个愿望一次满足)

    trie合并的裸题...因为最多只有n个点,所以最多合并n次,复杂度$O(N*26)$. #include<iostream> #include<cstring> #inclu ...

  9. 流媒体协议之RTSP客户端的实现20171014

    RtspClient是基于jrtplib实现的,目前仅支持h264格式,后续将不断迭代优化,加入对其他格式的支持,并且将实现RTSP的服务端. RtspClient的功能是接收服务端过来流,然后写入到 ...

  10. C++之高级编程20170914

    /*************************************************************************************************** ...