本文将介绍下Linux中的工作队列,并给出具体的demo。

1. 为什么要有工作队列

可以参见Work Queues

简单来说,工作队列(work queue)是Linux kernel中将工作推后执行的一种机制。这种机制和Tasklets不同之处在于工作队列是把推后的工作交由一个内核线程去执行,因此工作队列的优势就在于它允许重新调度甚至睡眠。

2. 数据结构

kernel version : v5.3-rc5

1
2
3
4
5
struct work_struct {
atomic_long_t data; //data用来存储用户的私人数据,此数据即是func的参数
struct list_head entry;
work_func_t func; //函数指针,由用户实现
};

The work queues allow kernel functions to be activated (much like deferrable functions) and later executed by special kernel threads called worker threads.

3. demo

Simple example of workqueue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/slab.h>

MODULE_LICENSE("Dual BSD/GPL");

#define printd() \
printk(KERN_ALERT "workqueue_test: %s %d\n", __FUNCTION__, __LINE__);


struct workqueue_struct *wq;

struct work_data {
struct work_struct work;
int data;
};

static void
work_handler(struct work_struct *work)
{
struct work_data * data = (struct work_data *)work;
printd();
kfree(data);
}


static int
wq_init(void)
{
struct work_data * data;

printd();
wq = create_workqueue("wq_test");
data = kmalloc(sizeof(struct work_data), GFP_KERNEL);
INIT_WORK(&data->work, work_handler);
queue_work(wq, &data->work);

return 0;
}

static void
wq_exit(void)
{
printd();
flush_workqueue(wq);
destroy_workqueue(wq);
printd();
}

module_init(wq_init);
module_exit(wq_exit);

Results:

1
2
3
4
workqueue_test: wq_init 33
workqueue_test: work_handler 23
workqueue_test: wq_exit 45
workqueue_test: wq_exit 48

具体函数的api去lxr中查询。


参考资料:

  1. Linux中的工作队列
  2. Shan Yizhou notes:Linux Work Queue