INIT_DELAYED_WORK() 函数的简单理解
INIT_DELAYED_WORK() 函数
应用场景
在中断中处理太多的操作是非常危险的,对中断的及时响应有很大的影响,在linux中我们经常会用到INIT_DELAYED_WORK,来处理中断需要响应的操作。
函数功能
工作队列(work queue)是Linux内核中将操作延期执行的一种机制。INIT_DELAYED_WORK()是一个宏
函数位置
\kernel\include\linux\workqueue.h
函数原型
#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)
实例:
#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");
输出:
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里面,主要标黄的部分的返回值与位置。
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,用法和没有延后的差不多。