[Linux API]linux 工作队列workqueue

Linux工作队列(Workqueue)机制简化了内核线程的创建,允许任务推后执行并在内核线程上下文中运行,支持根据CPU数量动态调整线程数。工作队列包括工作项(work)、工作队列结构(workqueue_struct)和工作线程(worker thread)。创建工作队列使用`DECLARE_WORK`或`DECLARE_DELAYED_WORK`,初始化工作项用`INIT_WORK`,加入队列用`queue_work`,销毁队列用`destroy_workqueue`。工作队列常用于需要延迟执行或异步处理的任务。
摘要由CSDN通过智能技术生成

1,功能描述:

Linux中的Workqueue机制就是为了简化内核线程的创建。通过调用workqueue的接口就能创建内核线程。并且可以根据当前系统CPU的个 数创建线程的数量,使得线程处理的事务能够并行化。workqueue是内核中实现简单而有效的机制,他显然简化了内核daemon的创建,方便了用户的 编程。

工作队列(workqueue)是另外一种将工作推后执行的形式.工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。最重要的就是工作队列允许被重新调度甚至是睡眠。

2,结构体/源码相关

推后执行的任务叫做工作,对应的结构体

//参考文件 kernel/include/linux/workqueue.h
struct work_struct {
    atomic_long_t data;     //paramters of work func 宏做函数的参数
    struct list_head entry;   //work node point链接结构提指针  ,一个链表节点
    work_func_t func;    //deal with work func 处理工作的函数,typedef void (*work_func_t)(struct work_struct *work);
#ifdef CONFIG_LOCKDEP
    struct lockdep_map lockdep_map;
#endif
};
//参考文件 kernel/include/linux/workqueue.h
struct delayed_work {
    struct work_struct work;
    struct timer_list timer;

    /* target workqueue and CPU ->timer uses to queue ->work */
    struct workqueue_struct *wq;
    int cpu;
};

创建类型:

静态地创建工作项:

DECLARE_WORK(n, f)
DECLARE_DELAYED_WORK(n, f)

动态地创建工作项:

INIT_WORK(struct work_struct work, work_func_t func); 
PREPARE_WORK(struct work_struct work, work_func_t func); 
INIT_DELAYED_WORK(struct delayed_work work, work_func_t func); 
PREPARE_DELAYED_WORK(struct delayed_work work, work_func_t func); 

3相关术语

workqueue: 所有工作项(需要被执行的工作)被排列于该队列.
worker thread: 是一个用于执行 workqueue 中各个工作项的内核线程, 当 workqueue 中没有工作项时, 该线程将变为 idle 状态.
single threaded(ST): worker thread 的表现形式之一, 在系统范围内, 只有一个 worker thread 为 workqueue 服务.
multi threaded(MT): worker thread 的表现形式之一, 在多 CPU 系统上每个 CPU 上都有一个 worker thread 为 workqueue 服务.

4创建以及使用

PART1:工作队列

work_handler // work中任务具体操作函数,workqueue 中的每个工作完成之后就被移除 workqueue.返回类型必须是void,参数必须是struct work_struct *work 类型
config_gpio_work(struct work_struct *work)
create_singlethread_workqueue(name) //返回一个名字为 name 的struct ,不再使用时需要destroy_workqueue(struct workqueue_struct *wq)来释放此处的内存地址。

workqueue_struct队列结构体。ST模式
INIT_WORK(&work, work_handler);//初始化struct work_struct 结构体,
queue_work(queue, &work); //放入队列工作

destroy_workqueue(queue); //销毁队列。

代码实战

struct workqueue_struct *mWorkqueue; 

 struct m_work{   //自定义结构体,作为work struct的私有数据
 struct work_struct inner_work;   //具体的工作
void * paramter;   //需要传递的参数 void   指针类型,当然也可以直接使用work_struct-〉data传递参数
};

void config_gpio_work(struct work_struct *work)  //返回类型必须是void 
{
    struct m_work * mwork;
   int gpio_num;
   mwork=container_of(work,struct m_work,inner_work);//自定义的结构体,这个函数的使用
   gpio_num = *((int *)mwork->paramter);
   printk(KERN_INFO"the gpio get  a value of =====workqueue==%d= \n",gpio_num);
    return;
}

int handle_workqueue(int gpio_num)
{
   struct m_work * mwork;
   mwork = kzalloc(sizeof(struct m_work), GFP_ATOMIC);
   if(!mwork)
   {
   printk(KERN_INFO"=====kernel mwork initial faild ==========\n");
   return -1;
   }
   mwork->paramter = &gpio_num;//参数赋值
   INIT_WORK(&mwork->inner_work,config_gpio_work);//初始化
   if(mWorkqueue==NULL)
   {
          mWorkqueue=create_singlethread_workqueue("joymine_workqueue");
   }
  queue_work(mWorkqueue,&gpio_work)
kfree(mwork);
destroy_workqueue(mWorkqueue);
mWorkqueue=NULL;
mwork=NULL;//   不用了的指针,一定要释放内存再置空,避免野指针
 return 0;
}

ttp://blog.csdn.net/myarrow/article/details/8090504
http://blog.csdn.net/brucexu1978/article/details/7173100

5实践遇到的问题以及问题分析。

A,container_of(parm1,parm2,pram3)函数的使用

//问题一 A,container_of(parm1,parm2,pram3)函数的使用

/** 
* container_of - cast a member of a structure out to the containing structure 
* @ptr:        the pointer to the member. 
* @type:       the type of the container struct this is embedded in. 
* @member:     the name of the member within the struct. 
* */ 


#define container_of(ptr, type, member) ({                      \ 
const typeof( ((type *)0)->member ) *__mptr = (ptr);    \ 
(type *)( (char *)__mptr - offsetof(type,member) );})

**它的作用显而易见,那就是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针。
参考上面的用例。**

B:关于指针,动态分配内存,malloc,需要释放内存,然后将指针指向NULL

PART 2:CMWQ(Concurrency Managed Workqueue )
有空需要按照如下链接学习了解原理以及使用
http://www.wowotech.net/irq_subsystem/workqueue.html

附上头文件
kernel/include/linux/workqueue.h

/*
 * workqueue.h --- work queue handling for Linux.
 */

#ifndef _LINUX_WORKQUEUE_H
#define _LINUX_WORKQUEUE_H

#include <linux/timer.h>
#include <linux/linkage.h>
#include <linux/bitops.h>
#include <linux/lockdep.h>
#include <linux/threads.h>
#include <linux/atomic.h>
#include <linux/cpumask.h>

struct workqueue_struct;

struct work_struct;
typedef void (*work_func_t)(struct work_struct *work);
void delayed_work_timer_fn(unsigned long __data);

/*
 * The first word is the work queue pointer and the flags rolled into
 * one
 */
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值