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
*/