简介

Linux中断的下半部分有四种处理方式。

  • 工作队列
  • Threaded IRQ
  • Softirq
  • Tasklet

这一片文章我们讲述工作队列的使用

linux中的工作队列

Work queues在linux 2.6版本加入的。工作队列是推迟工作的另一种形式。工作队列将工作推迟到内核线程中。下半部分始终在流程上下文中运行。因为工作队列允许用户创建内核线程并将工作绑定到内核线程。
在内核中有两种方式实现Workqueue。

  • 使用全局的工作队列
  • 创建自己的工作队列

全局工作队列的使用

工作队列的初始化

可以分为静态和动态两种方式。

  1. # 静态
  2. DECLARE_WORK(workqueuename,workqueue_fn);
  3. # 动态

对应的API

  1. int schedule_work( struct work_struct *work );
  2. int scheduled_delayed_work( struct delayed_work *dwork, unsigned long delay );
  3. int schedule_work_on( int cpu, struct work_struct *work );
  4. int scheduled_delayed_work_on(
  5. int cpu, struct delayed_work *dwork, unsigned long delay );
  6. # 删除队列
  7. int flush_work( struct work_struct *work );
  8. void flush_scheduled_work( void );
  9. # 取消工作
  10. int cancel_work_sync( struct work_struct *work );
  11. int cancel_delayed_work_sync( struct delayed_work *dwork );
  12. # 检查工作
  13. work_pending( work );
  14. delayed_work_pending( work );

代码

静态使用

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/delay.h>
  4. #include <linux/workqueue.h>
  5. // struct workqueue_struct *workqueue_test;
  6. // struct work_struct work_test;
  7. void work_test_func(struct work_struct *work) { printk("now this static workqueue has run\n"); }
  8. /*Creating work by Static Method */
  9. DECLARE_WORK(workqueue,work_test_func);
  10. static int test_init(void) {
  11. schedule_work(&workqueue);
  12. return 0;
  13. }
  14. static void test_exit(void) {
  15. printk("Goodbye,cruel world!\n");
  16. // destroy_workqueue(workqueue_test);
  17. }
  18. module_init(test_init);
  19. module_exit(test_exit);
  20. MODULE_LICENSE("GPL");
  21. MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");
  22. MODULE_DESCRIPTION("A simple workqueue driver");
  23. MODULE_VERSION("2:1.0");

动态使用

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/delay.h>
  4. #include <linux/workqueue.h>
  5. /* Work structure */
  6. static struct work_struct workqueue;
  7. void work_test_func(struct work_struct *work) { printk("now this Dynamic workqueue has run\n"); }
  8. static int test_init(void) {
  9. /*Creating work by Dynamic Method */
  10. INIT_WORK(&workqueue,work_test_func);
  11. schedule_work(&workqueue);
  12. return 0;
  13. }
  14. static void test_exit(void) {
  15. printk("Goodbye,cruel world!\n");
  16. }
  17. module_init(test_init);
  18. module_exit(test_exit);
  19. MODULE_LICENSE("GPL");
  20. MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");
  21. MODULE_DESCRIPTION("A simple workqueue driver");
  22. MODULE_VERSION("2:1.0");

创建自己的WorkQueue & 传递参数

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/delay.h>
  4. #include <linux/workqueue.h>
  5. struct workqueue_struct *workqueue_test;
  6. struct Mywork_struct
  7. {
  8. struct work_struct work_test;
  9. char *str;
  10. int Id;
  11. };
  12. struct Mywork_struct Mywork_struct[2];
  13. static char teststr[] = "test for demo work";
  14. void work_test_func(struct work_struct *work)
  15. {
  16. struct Mywork_struct *PMyWork = container_of(work, struct Mywork_struct, work_test);
  17. printk("Id == %d,%s\n", PMyWork->Id, PMyWork->str);
  18. }
  19. static int test_init(void)
  20. {
  21. int i = 0x00;
  22. printk("Hello,world!\n");
  23. /* 1. 自己创建一个workqueue, 中间参数为0,默认配置 */
  24. /* 或者也可以 create_workqueue
  25. workqueue_test = create_workqueue("workqueue_test");*/
  26. workqueue_test = alloc_workqueue("workqueue_test", 0, 0);
  27. /*Creating workqueue */
  28. for (i = 0x0; i < sizeof(Mywork_struct) / sizeof(Mywork_struct[0]); i++)
  29. {
  30. /* 2. 初始化工作项,并添加自己实现的函数 */
  31. INIT_WORK(&Mywork_struct[i].work_test, work_test_func);
  32. Mywork_struct[i].Id = i;
  33. Mywork_struct[i].str = teststr;
  34. }
  35. /* 3. 将自己的工作项添加到指定的工作队列去, 同时唤醒相应线程处理 */
  36. for (i = 0x0; i < sizeof(Mywork_struct) / sizeof(Mywork_struct[0]); i++)
  37. {
  38. queue_work(workqueue_test, &Mywork_struct[i].work_test);
  39. }
  40. return 0;
  41. }
  42. static void test_exit(void)
  43. {
  44. printk("Goodbye,cruel world!\n");
  45. destroy_workqueue(workqueue_test);
  46. }
  47. module_init(test_init);
  48. module_exit(test_exit);
  49. MODULE_LICENSE("GPL");
  50. MODULE_AUTHOR("zhouchengzhu <1073355312@qq.com>");
  51. MODULE_DESCRIPTION("A simple workqueue driver");
  52. MODULE_VERSION("2:1.0");

参考资料