Chinaunix首页 | 论坛 | 博客
  • 博客访问: 306687
  • 博文数量: 27
  • 博客积分: 1933
  • 博客等级: 上尉
  • 技术积分: 884
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-04 23:34
文章分类

全部博文(27)

文章存档

2013年(3)

2011年(24)

分类:

2013-01-04 14:00:16

原文地址:工作队列 作者:add358

1 "工作队列"用途
 工作队列用途跟tasklet相似,在中断处理时将一些非紧急的任务留到工作队列中完成,而紧急的任务则在硬中断服务程序中完成。
 但工作队列与tasklet还是有很大的区别:
 1)工作队列函数在一个特殊内核进程的上下文中运行;
 2)tasklet会在很短的时间段内很快执行,且以原子模式执行;
    而工作队列函数具有更长的延迟并且不需要原子模式;
 3)工作队列函数可以休眠;

2 "工作队列"结构

  注意:2.6.20之后,工作队列的数据结构发生了不少变化,这里列出的接口与数据结构是基于3.2.1的。
  1. #include
  2. struct workqueue_struct {/*定义在kernel/workqueue.c*/}; /*工作队列结构*/

  3. struct work_struct {       /*向工作队列提交一个任务的任务结构*/
  4.     atomic_long_t data;
  5.     struct list_head entry;
  6.     work_func_t func;     /*work_func_t 定义如下*/
  7.     /*省略其他成员变量*/
  8. }
  9. typedef void (*work_func_t)(struct work_struct *work);

3 "工作队列"接口

 这里只列出一些重要的接口,如果想查看更多接口,可参看"linux/workqueue.h"文件。
 3.1 创建工作队列
  1. /*这两个是宏,使用时name不用加双引号,这里这样写只是更好地表达该宏的用途*/
  2. struct workqueue_struct *create_workqueue(const char *name) /*在系统中的每个处理器上
  3.                                                               为该工作队列创建专用线程*/
  4. struct workqueue_struct *create_singlethread_workqueue(const char *name) /*只创建一个
  5.                                                                            专用线程*/
 3.2 创建工作(work_struct)
  1. DECLARE_WORK(name,func); /*定义名为name的work_struct类型变量,使用时name不用加双引号,
  2.                            func是work_func_t类型*/

  3. INIT_WORK(struct work_struct *work,work_func_t func); /*添充work变量,首次构造该结构时使用*/
  4. INIT_DELAYED_WORK(struct work_struct *work,work_func_t func); 
  5. PREPARE_WORK(struct work_struct *work,work_func_t func); /*如果工作已提交到工作队列时,
  6.                                                            而只需修改该结构时使用*/
 3.3 提交工作到工作队列
  1. int queue_work(struct workqueue_struct *wq, struct work_struct *work);
  2. int queue_delayed_work(struct workqueue_struct *wq, struct_work *work,
  3.                        unsigned long delay); /*工作至少会被延迟delay后被执行*/
 3.4 取消工作
  1. int cancel_delayed_work(struct work_struct *work); /*如果工作在开始执行前被取消,则返回非零值*/
  2. void flush_workqueue(struct workqueue_struct *wq); /*该函数返回后,任何在该函数调用之前
  3.                                                      被提交的工作都不会在系统任何地方运行*/
 3.5 销毁"工作队列"
  1. void destroy_workqueue(struct workqueue_struct *queue);
4 共享队列
 如果对工作队列使用不是很频繁的话,则可以使用内核提供的共享的默认队列;需要注意的是,使用该共享队列时不应该长期独占它,而且任务可能需要等待更长的时间后才被执行;一般情况下,推荐使用共享队列。
 共享队列接口
  1. int schedule_work(struct work_struct *work); /*提交工作任务到共享队列*/
  2. int schedule_delayed_work(struct work_struct *work,unsigned long delay);
  3. void flush_scheduled_work(void);
5 示例代码
 这里只是演示如何使用“工作队列”,并没有在中断处理中使用。
 5.1 自己创建工作队列    workqueue.rar  

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/workqueue.h>

  4. MODULE_LICENSE("Dual BSD/GPL");
  5. MODULE_AUTHOR("Kozo");

  6. struct my_struct{
  7.     char *name;
  8.     struct work_struct my_work;
  9. };

  10. static void display(struct work_struct *work)
  11. {
  12.     struct my_struct *my_name = container_of(work,struct my_struct, my_work);
  13.     printk(KERN_DEBUG"name = %s\n",my_name->name);
  14. }

  15. static struct workqueue_struct *my_wq;  /*注意要全局变量*/
  16. static struct my_struct my_name;        /*注意要全局变量*/

  17. static int __init demo_init(void)
  18. {
  19.     my_wq = create_workqueue("my wq");
  20.     my_name.name = "Kozo";
  21.     INIT_WORK(&(my_name.my_work), display);
  22.     queue_work(my_wq,&(my_name.my_work));
  23.     return 0;
  24. }

  25. static void __exit demo_exit(void)
  26. {
  27.     printk(KERN_DEBUG"Goodbye\n");
  28.     destroy_workqueue(my_wq);
  29. }
  30. module_init(demo_init);
  31. module_exit(demo_exit);
  5.2 使用共享队列    sharequeue.rar  

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/workqueue.h>

  4. MODULE_LICENSE("Dual BSD/GPL");
  5. MODULE_AUTHOR("Kozo");

  6. struct my_struct{
  7.     char *name;
  8.     struct work_struct my_work;
  9. };

  10. static void display(struct work_struct *work)
  11. {
  12.     struct my_struct *my_name = container_of(work,struct my_struct, my_work);
  13.     printk(KERN_DEBUG"name = %s\n",my_name->name);
  14. }

  15. static struct my_struct my_name;

  16. static int __init demo_init(void)
  17. {
  18.     my_name.name = "Kozo";
  19.     INIT_WORK(&(my_name.my_work), display);
  20.     schedule_work(&(my_name.my_work));
  21.     return 0;
  22. }

  23. static void __exit demo_exit(void)
  24. {
  25.     printk(KERN_DEBUG"Goodbye\n");
  26.     flush_scheduled_work();
  27. }
  28. module_init(demo_init);
  29. module_exit(demo_exit);
6 执行结果


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






阅读(2862) | 评论(0) | 转发(0) |
0

上一篇:LCD的SPI接口分析

下一篇:定时器(timer)

给主人留下些什么吧!~~