Linux内核workqueue,Linux设备驱动之workqueue

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

工作队列是一种将工作推后执行的形式,交由一个内核线程去执行在进程上下文执行,其不能访问用户空间。最重要特点的就是工作队列允许重新调度甚至是睡眠。

在内核代码中, 经常希望延缓部分工作到将来某个时间执行, 这样做的原因很多, 比如在持有锁时做大量(或者说费时的)工作不合适。

希望将工作聚集以获取批处理的性能。

调用了一个可能导致睡眠的函数使得在此时执行新调度非常不合适。

内核中提供了许多机制来提供延迟执行, 使用最多则是 workqueue。

工作队列(workqueue)是另外一种将工作推后执行的形式.工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。最重要的就是工作队列允许被重新调度甚至是睡眠。

对于使用者,基本上只需要做 3 件事情,依次为:创建工作队列 ( 如果使用内核默认的工作队列,连这一步都可以省略掉 )

创、建工作项

向工作队列中提交工作项

执行在进程上下文中,这样使得它可以睡眠,被调度及被抢占,在多核环境下的使用也非常友好。

数据结构工作:

所谓work就是异步执行的函数。用数据结构 struct work_struct 表示。

工作队列: struct workqueue_struct

如果是多线程,Linux根据当前系统CPU的个数创建 struct cpu_workqueue_struct:

包含的头文档为

创建步骤

静态地创建work工作:

静态地创建一个名为n,待执行函数为f,函数的参数为data的work_struct结构。1

2

3

4

5#define DECLARE_WORK(n, f)

struct work_struct n = __WORK_INITIALIZER(n, f)

#define DECLARE_DELAYED_WORK(n, f)

struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f)

一般而言,work都是推迟到worker thread被调度的时刻,但是有时候,我们希望在指定的时间过去之后再调度worker thread来处理该work,这种类型的work被称作delayed work,DECLARE_DELAYED_WORK用来初始化delayed work,它的概念和普通work类似。

动态地创建work工作:

动态创建初始化的时候需要把work的指针传递给 INIT_WORK 。1

2

3

4INIT_WORK(struct work_struct work, work_func_t func);

PREPARE_WORK(struct work_struct work, work_func_t func);

INIT_DELAYED_WORK(struct delayed_work work, work_func_t func);

PREPARE_DELAYED_WORK(struct delayed_work work, work_func_t func);

清除或取消工作队列中的work工作

想清理特定的任务项目并阻塞任务, 直到任务完成为止, 可以调用 flush_work 来实现。

指定工作队列中的所有任务能够通过调用 flush_workqueue 来完成。 这两种情形下,调用者阻塞直到操作完成为止。

为了清理内核全局工作队列,可调用 flush_scheduled_work。1

2

3int flush_work( struct work_struct *work );

int flush_workqueue( struct workqueue_struct *wq );

void flush_scheduled_work( void );

还没有在处理进程当中执行的任务可以被取消。 调用 cancel_work_sync 将会终止队列中的任务或者阻塞任务直到回调结束(如果处理进程已经在处理该任务)。 如果任务被延迟,可以调用 cancel_delayed_work_sync 。1

2int cancel_work_sync( struct work_struct *work );

int cancel_delayed_work_sync( struct delayed_work *dwork );

最后,可以通过调用 work_pending 或者 delayed_work_pending 来确定任务项目是否在进行中。1

2work_pending( work );

delayed_work_pending( work );

创建销毁workqueue用于创建一个workqueue队列,为系统中的每个CPU都创建一个内核线程。1struct workqueue_struct *create_workqueue(const char *name);

用于创建workqueue,只创建一个内核线程。1struct workqueue_struct *create_singlethread_workqueue(const char *name);

释放workqueue队列。1void destroy_workqueue(struct workqueue_struct *queue);

使用内核提供的共享列队

系统中包括若干的workqueue,最著名的workqueue就是系统缺省的的工作队列 keventd_wq 了,定义如下:1static struct workqueue_struct *keventd_wq __read_mostly;对工作进行调度,即把给定工作的处理函数提交给缺省的工作队列和工作线程。1int schedule_work(struct work_struct *work);

确保没有工作队列入口在系统中任何地方运行。1void flush_scheduled_work(void);

延时执行一个任务1int schedule_delayed_work(struct delayed_struct *work, unsigned long delay);

从一个工作队列中去除入口;1int cancel_delayed_work(struct delayed_struct *work);

使用自定义队列将工作加入工作列队进行调度1int queue_work(struct workqueue_struct *wq, struct work_struct *work)

释放创建的工作列队资源1void destroy_workqueue(struct workqueue_struct *wq)

延时调用指定工作列队的工作1queue_delayed_work(struct workqueue_struct *wq, struct delay_struct *work, unsigned long delay)

取消指定工作列队的延时工作1cancel_delayed_work(struct delay_struct *work)

等待列队中的任务全部执行完毕。1void flush_workqueue(struct workqueue_struct *wq);

样例代码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/* https://github.com/cirosantilli/linux-kernel-module-cheat#workqueues */

#include

#include

#include

static struct workqueue_struct *queue;

static void work_func(struct work_struct *work)

{

printk(KERN_INFO "workern");

}

DECLARE_WORK(work, work_func);

static int myinit(void)

{

queue = create_workqueue("myworkqueue");

queue_work(queue, &work);

return 0;

}

static void myexit(void)

{

destroy_workqueue(queue);

}

module_init(myinit)

module_exit(myexit)

MODULE_LICENSE("GPL");

参考

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值