yyg-cn

导航

统计

INIT_DELAYED_WORK() 函数的简单理解

 
INIT_DELAYED_WORK() 函数
应用场景
在中断中处理太多的操作是非常危险的,对中断的及时响应有很大的影响,在linux中我们经常会用到INIT_DELAYED_WORK,来处理中断需要响应的操作。
函数功能
工作队列(work queue)是Linux内核中将操作延期执行的一种机制。INIT_DELAYED_WORK()是一个宏
函数位置
\kernel\include\linux\workqueue.h
 
函数原型
 
1
2
3
4
5
6
7
#define __INIT_DELAYED_WORK(_work, _func, _tflags)        \
 do {        \
  INIT_WORK(&(_work)->work, (_func));        \
  __setup_timer(&(_work)->timer, delayed_work_timer_fn,        \
         (unsigned long)(_work),        \
         (_tflags) | TIMER_IRQSAFE);        \
 } while (0)

 实例:

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
53
54
55
56
57
58
59
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
struct delayed_work mdwq;
struct workqueue_struct *mwq;
void delay_work_func(struct work_struct *work)
{
int i;
  
printk(KERN_INFO "%s:%d----%d,%s\n",__FUNCTION__,__LINE__,current->pid,current->comm);
for (i = 0; i < 3; i++) {
printk(KERN_ERR "%s:i=%d %d,%s\n",__FUNCTION__,i,current->pid,current->comm);
msleep(3000);
}
}
  
static int __init delay_work_init(void)
{
int ret;
int i;
mwq = create_workqueue("my workqueue");
if (!mwq) {
printk(KERN_ERR "Create workqueue failed!\n");
return 1;
}
printk(KERN_INFO "Create workqueue successful!\n");
  
INIT_DELAYED_WORK(&mdwq, delay_work_func);
  
ret = queue_delayed_work(mwq, &mdwq, 3000);
printk(KERN_INFO "first ret=%d!\n", ret);
  
for (i = 0; i < 3; i++) {
printk(KERN_INFO "%s:ret=%d,i=%d-----%d,%s\n",__FUNCTION__,ret, i,current->pid,current->comm);
msleep(1000);
}
  
ret = queue_delayed_work(mwq, &mdwq, 0);
printk(KERN_INFO "second ret=%d!\n", ret);
  
return 0;
}
  
static void __exit delay_work_exit(void)
{
int ret;
ret = cancel_delayed_work(&mdwq);
flush_workqueue(mwq);
destroy_workqueue(mwq);
printk(KERN_INFO "Exit! ret=%d\n", ret);
}
module_init(delay_work_init);
module_exit(delay_work_exit);
MODULE_LICENSE("GPL");

 输出:

1
2
3
4
5
6
7
8
9
10
11
Nov  9 16:01:17 witch kernel: [ 1450.932918] Create workqueue successful!
Nov  9 16:01:17 witch kernel: [ 1450.932919] first ret=1!
Nov  9 16:01:17 witch kernel: [ 1450.932919] delay_work_init:ret=1,i=0-----8305,insmod
Nov  9 16:01:18 witch kernel: [ 1451.966574] delay_work_init:ret=1,i=1-----8305,insmod
Nov  9 16:01:19 witch kernel: [ 1452.990607] delay_work_init:ret=1,i=2-----8305,insmod
Nov  9 16:01:20 witch kernel: [ 1454.014634] second ret=0!
Nov  9 16:01:29 witch kernel: [ 1463.006864] delay_work_func:15----8308,kworker/11:0
Nov  9 16:01:29 witch kernel: [ 1463.006868] delay_work_func:i=0  8308,kworker/11:0
Nov  9 16:01:32 witch kernel: [ 1466.078821] delay_work_func:i=1  8308,kworker/11:0
Nov  9 16:01:35 witch kernel: [ 1469.151040] delay_work_func:i=2  8308,kworker/11:0
Nov  9 16:01:39 witch kernel: [ 1472.223119] Exit! ret=0
特别注意:这里的delay_work_func实际上只调用一次,两次调用queue_delayed_work是检查work在不在workqueue里面,主要标黄的部分的返回值与位置。
1
2
3
bool queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *dwork,
unsigned long delay);
两个函数的返回值:
返回0,表示work在这之前,已经在workqueue中了
返回非0,表示work成功加入到workqueue中了
queue_delayed_work表示不是马上把work加入到workqueue中,而是延后delay(时间单位jiffies),再加入。注意它的work(dwork)要用宏(静态)DECLARE_DELAYED_WORK来定义和初始化,动态的可以用INIT_DELAYED_WORK,用法和没有延后的差不多。

posted on   干饭的鸭鸭怪  阅读(2431)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示