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,用法和没有延后的差不多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具