工作队列

来源:互联网 发布:淘宝众筹玩法 编辑:程序博客网 时间:2024/04/30 09:52
1 "工作队列"用途
 工作队列用途跟tasklet相似,在中断处理时将一些非紧急的任务留到工作队列中完成,而紧急的任务则在硬中断服务程序中完成。
 但工作队列与tasklet还是有很大的区别:
 1)工作队列函数在一个特殊内核进程的上下文中运行;
 2)tasklet会在很短的时间段内很快执行,且以原子模式执行;
    而工作队列函数具有更长的延迟并且不需要原子模式;
 3)工作队列函数可以休眠;

2 "工作队列"结构

  注意:2.6.20之后,工作队列的数据结构发生了不少变化,这里列出的接口与数据结构是基于3.2.1的。

#include<linux/workqueue.h>struct workqueue_struct {/*定义在kernel/workqueue.c*/}; /*工作队列结构*/struct work_struct {       /*向工作队列提交一个任务的任务结构*/    atomic_long_t data;    struct list_head entry;    work_func_t func;     /*work_func_t 定义如下*/    /*省略其他成员变量*/}typedef void (*work_func_t)(struct work_struct *work);

3 "工作队列"接口
 这里只列出一些重要的接口,如果想查看更多接口,可参看"linux/workqueue.h"文件。
 3.1 创建工作队列

/*这两个是宏,使用时name不用加双引号,这里这样写只是更好地表达该宏的用途*/struct workqueue_struct *create_workqueue(const char *name) /*在系统中的每个处理器上为该工作队列创建专用线程*/struct workqueue_struct *create_singlethread_workqueue(const char *name) /*只创建一个专用线程*/
3.2 创建工作(work_struct)

DECLARE_WORK(name,func); /*定义名为name的work_struct类型变量,使用时name不用加双引号,func是work_func_t类型*/INIT_WORK(struct work_struct *work,work_func_t func); /*添充work变量,首次构造该结构时使用*/INIT_DELAYED_WORK(struct work_struct *work,work_func_t func); PREPARE_WORK(struct work_struct *work,work_func_t func); /*如果工作已提交到工作队列时,而只需修改该结构时使用*/
 3.3 提交工作到工作队列
int queue_work(struct workqueue_struct *wq, struct work_struct *work);int queue_delayed_work(struct workqueue_struct *wq, struct_work *work,unsigned long delay); /*工作至少会被延迟delay后被执行*/
3.4 取消工作
int cancel_delayed_work(struct work_struct *work); /*如果工作在开始执行前被取消,则返回非零值*/void flush_workqueue(struct workqueue_struct *wq); /*该函数返回后,任何在该函数调用之前被提交的工作都不会在系统任何地方运行*/
3.5 销毁"工作队列"
void destroy_workqueue(struct workqueue_struct *queue);
4 共享队列
 如果对工作队列使用不是很频繁的话,则可以使用内核提供的共享的默认队列;需要注意的是,使用该共享队列时不应该长期独占它,而且任务可能需要等待更长的时间后才被执行;一般情况下,推荐使用共享队列。
 共享队列接口
int schedule_work(struct work_struct *work); /*提交工作任务到共享队列*/int schedule_delayed_work(struct work_struct *work,unsigned long delay);void flush_scheduled_work(void);
5 示例代码
 这里只是演示如何使用“工作队列”,并没有在中断处理中使用。
 5.1 自己创建工作队列
#include <linux/module.h>#include <linux/init.h>#include <linux/workqueue.h>MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("Kozo");struct my_struct{    char *name;    struct work_struct my_work;};static void display(struct work_struct *work){    struct my_struct *my_name = container_of(work,struct my_struct, my_work);    printk(KERN_DEBUG"name = %s\n",my_name->name);}static struct workqueue_struct *my_wq;  /*注意要全局变量*/static struct my_struct my_name;        /*注意要全局变量*/static int __init demo_init(void){    my_wq = create_workqueue("my wq");    my_name.name = "Kozo";    INIT_WORK(&(my_name.my_work), display);    queue_work(my_wq,&(my_name.my_work));/*转着注:类似于schedule_work,区别在于queue_work把给定工作提交给创建的工作队列wq而不是缺省队列。*/    return 0;}static void __exit demo_exit(void){    printk(KERN_DEBUG"Goodbye\n");    destroy_workqueue(my_wq);}module_init(demo_init);module_exit(demo_exit);
 5.2 使用共享队列
#include <linux/module.h>#include <linux/init.h>#include <linux/workqueue.h>MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("Kozo");struct my_struct{    char *name;    struct work_struct my_work;};static void display(struct work_struct *work){    struct my_struct *my_name = container_of(work,struct my_struct, my_work);    printk(KERN_DEBUG"name = %s\n",my_name->name);}static struct my_struct my_name;static int __init demo_init(void){    my_name.name = "Kozo";    INIT_WORK(&(my_name.my_work), display);    schedule_work(&(my_name.my_work));    return 0;}static void __exit demo_exit(void){    printk(KERN_DEBUG"Goodbye\n");    flush_scheduled_work();}module_init(demo_init);module_exit(demo_exit);
6 执行结果

转载本文时请注明出自:add358.blog.chinaunix.net

0 0