工作队列(workqueue)

http://blog.csdn.net/mcgrady_tracy/article/details/42264995

工作队列类似于tasklet,它允许内核代码请求某个函数在将来被执行(不是立即执行)。

工作队列相关API定义在<linux/workqueue.h>中。要使用工作队列有两种方式,一是自己创建一个工作队列;二是使用内核提供的工作队列(共享方式)。


一、我们先来看自己创建工作队列的方式

工作队列使用结构体struct workqueue_struct描述,要创建一个工作队列有两个API,即create_workqueue和create_singlethread_workqueue,原型如下:

  1. struct workqueue_struct *create_workqueue(const char *name);  
  2. struct workqueue_struct *create_singlethread_workqueue(const char *name);  
例如:
  1. struct workqueue_struct *keventd_wq;  
  2. keventd_wq = create_workqueue("events");  
create_workqueue函数会在系统中的每个处理器上创建一个线程(多线程),而create_singlethread_workqueue只是创建一个单一的线程,如果单个线程足够使用,那么应该使用create_singlethread_workqueue函数。

要向工作队列中提交一个任务,首先需要填充一个struct work_struct,延时任务使用struct delayed_work,内核提供了相关宏:
  1. DECLARE_WORK(name, void (*func)(void *));  
  2. INIT_WORK(struct work_struct *work, void (*func)(void *));  
DECLARE_WORK宏用于静态定义一个work_struct。而INIT_WORK宏用于动态初始化一个work_struct。

延时任务使用INIT_DELAYED_WORK宏初始化。

  1. INIT_DELAYED_WORK(struct delayed_work, void (*func)(void *));  

要将任务提交到工作队列中,内核提供了下面两个API:
  1. int queue_work(struct workqueue_struct *wq, struct work_struct *work);  
  2. int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work, unsigned long delay);  
这两个函数都会将任务提交到工作队列中,使用queue_delayed_work函数,则提交的任务至少延时由参数delay指定的时间才被执行。

如果要取消工作队列中的某个任务,使用cancel_delayed_work,原型如下:
  1. int cancel_delayed_work(struct work_struct *work);  
如果任务在被执行之前取消,那么cancel_delayed_work函数返回非零值,调用该函数之后内核会确保被取消的任务不被执行。但是返回0,则表示任务已经被执行,因此调用cancel_delayed_work函数后,任务有可能仍在运行,所以为了确保任务测地被取消,需要调用flush_workqueue函数。
  1. void flush_workqueue(struct workqueue_struct *wq);  

使用完工作队列之后,可以使用destroy_workqueue销毁工作队列:
  1. void destroy_workqueue(struct workqueue_struct *wq);  


二、使用内核的共享工作队列

内核在初始化时创建了一个工作队列"events",这个工作队列是共享的,所以我们可以向这个队列提交简单的任务处理。

由于这个工作队列已经被创建好了,所以不再需要我们去创建了,直接往工作队列提交任务就可以了,内核为我们提供了相关API:

  1. int schedule_work(struct work_struct *work);  
  2. int schedule_delayed_work(struct delayed_work *work, unsigned long delay);  
而这两个函数最终还是调用的前面内核提供的函数,只是工作队列为内核中的keventd_wq。

如果要取消提交到共享工作队列中的任务,同样可以使用前面的cancel_delayed_work函数,如果cancel_delayed_work函数返回0,不再使用前面的flush_workqueue函数了,而是使用flush_scheduled_work函数。
  1. void flush_scheduled_work(void); 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值