在驱动中,有时不能使用中断(这种情况很少遇到),此时delayed_workqueue就可以发挥其巨大的功效了。也可以用其它同类的内核API实现:如timer.delayed_workqueue的使用过程如下:

(1)定义workqueue: struct workqueue_struct *test_workqueue; //  kernel/workqueue.c

(2)定义workqueue要做的delayed工作:struct delayed_work test_delayed_work;// include/linux/workqueue.h

(3)初始化workqueue:INIT_DELAYED_WORK(&test_delayed_work,test_workqueue_func); //定义在:include/linux/workqueue.h

(4) 创建线程queue并加以名字:test_workqueue = create_singlethread_workqueue("name_of_this_queue");

(5)运行queue:queue_delayed_work(test_workqueue, &test_delayed_work, delay_time); //定义在:kernel/workqueue.c, 其中delay_time是延迟多少时间来运行queue。

注: 在test_workqueu_func中一定要再次将delayed_workqueue加入queue中,即再次运行queue_delayed_work。否则,此queue只运行一次。

下面详细讲解每个函数。

#define INIT_DELAYED_WORK(_work, _func)             \  
  1. do {                            \
  2. INIT_WORK(&(_work)->work, (_func));      \
  3. init_timer(&(_work)->timer);         \
  4. } while (0)
#define INIT_DELAYED_WORK(_work, _func)              \do {                           \INIT_WORK(&(_work)->work, (_func));     \init_timer(&(_work)->timer);            \} while (0)
#define INIT_WORK(_work, _func)                     \  

do {                                \

  1. (_work)->data = (atomic_long_t) WORK_DATA_INIT();    \
  2. INIT_LIST_HEAD(&(_work)->entry);         \
  3. PREPARE_WORK((_work), (_func));             \
  4. } while (0)
  5. #endif
  6. // WORK_DATA_INIT() == 0;
  7. // PREPARE_WORK((_work), (_func)) == (_work)->func = (_func);
  8. struct delayed_work {
  9. struct work_struct work;
  10. struct timer_list timer;
  11. };
#define INIT_WORK(_work, _func)                      \do {                               \(_work)->data = (atomic_long_t) WORK_DATA_INIT();  \INIT_LIST_HEAD(&(_work)->entry);            \PREPARE_WORK((_work), (_func));                \} while (0)
#endif// WORK_DATA_INIT() == 0;
// PREPARE_WORK((_work), (_func)) == (_work)->func = (_func);struct delayed_work {struct work_struct work;struct timer_list timer;
};

INIT_WORK的主要工作是data赋值为0; 初始化entry链表;将_func传给work的_func。

#define init_timer(timer) init_timer_key((timer), NULL, NULL)  
#define init_timer(timer) init_timer_key((timer), NULL, NULL)

init_timer_key((timer), NULL, NULL) --> debug_time_init [ NOP]

使用delayed workqueue最主要的是调用queue_delayed_work。如果delay = 0,则直接调用:queue_work 其具体实现过程:queue_work --> queue_work_on --> __queue_work --> insert_work

如果delay !=0,则调用:queue_delayed_work_on

其具体实现过程:queue_delayed_work_on 此函数是通过timer来完成最后的延时工作。

Linux驱动中delayed_workqueue使用:相关推荐

  1. Linux设备驱动开发-linux驱动中的阻塞访问方式

    阻塞与非阻塞是设备访问的两种不同的模式.什么是阻塞操作呢?其是指在执行设备操作的时候,如果不能获得资源,则挂起进程直到满足可操作的条件后再进行操作.而非阻塞操作则是在进程不能进行设备操作时,并不挂起到 ...

  2. linux probe函数调用,【整理】Linux驱动中,probe函数何时被调用

    [整理]Linux驱动中,probe函数何时被调用 用SourceInsight跟踪: 从driver_register看起,此处我的这里是: int driver_register(struct d ...

  3. Linux驱动中delayed workqueue用法

    在驱动中,有时不能使用中断(这种情况很少遇到), 此时delayed_workqueue就可以发挥其巨大的功效了.也可以用其它同类的内核API实现:如timer.delayed_workqueue就相 ...

  4. Linux驱动中,probe函数何时被调用

    最近看到linux的设备驱动模型,关于Kobject.Kset等还不是很清淅.看到了struct device_driver这个结构时,想到一个问题:它的初始化函数到底在哪里调用呢?以前搞PCI驱动时 ...

  5. linux platform匹配机制,Linux驱动中的platform总线详解

    platform总线是学习linux驱动必须要掌握的一个知识点. 一.概念 嵌入式系统中有很多的物理总线:I2c.SPI.USB.uart.PCIE.APB.AHB linux从2.6起就加入了一套新 ...

  6. linux驱动中使用定时器

    我的内核是2.4.18的.Linux的内核中定义了一个定时器的结构: #include<linux/timer.h> struct timer_list { structlist_head ...

  7. linux驱动中probe函数是怎么调用的

    linux驱动的三个概念:设备.驱动.总线 probe何时被调用:在总线上驱动和设备的名字匹配,就会调用驱动的probe函数 probe函数被调用后,系统就调用platform设备的probe函数完成 ...

  8. Linux驱动中按键消抖原理

    为什么要用定时器来做按键消抖? 用到按键就要处理因为机械结构带来的按键抖动问题,也就是按键消抖.前面的实验中都是直接使用了延时函数来实现消抖,因为简单,但是直接用延时函数来实现消抖会浪费 CPU 性能 ...

  9. 【整理】Linux驱动中,probe函数何时被调用

    声明:以下主要内容参考自: 关于struct device_driver结构中的probe探测函数的调用 http://blog.chinaunix.net/u2/71164/showart.php? ...

  10. linux驱动中printk的使用注意事项

    今天在按键驱动中增加printk(KERN_INFO "gpio_keys_gpio_isr()\n");在驱动加载阶段可以输出调试信息,但驱动加载起来后的信息,在串口端看不到输出 ...

最新文章

  1. (013)java后台开发之Mac系统安装和配置tomcat步骤详解
  2. 5G 与边缘计算的发展现状(2021 年 6 月)
  3. 梯度下降算法到logistic回归
  4. Coding中遇到的BUG集合~
  5. Dataset:机器学习和深度学习中对数据集进行高级绘图(数据集可视化,箱线图等)的简介、应用之详细攻略——daidingdaiding
  6. elasticsearch 基本配置
  7. zoj 3209 Dancing links/hust 1017
  8. x86 32位oracle,X86 32位和64位的区别
  9. html禁止页面左右滑动,js阻止移动端默认事件以及只阻止横向滚动事件方法
  10. Atlantis poj1151 线段树扫描线
  11. 黑苹果OC引导注入_黑苹果OC配置工具:OpenCore Configurator v2.15.2.0
  12. 【Spring-DEBUG记录】Dependency ‘org.aspectj:aspectjweaver:‘ not found
  13. 微信小程序开发者文档教程,从入门到精通 (附超过100个完整项目源代码、文档)
  14. Flink DataStream Keyed和Non-Keyed窗口、WindowAssigner、窗口生命周期、窗口函数、迟到数据和窗口结果的处理
  15. C++/MFC修行之路(5)Ribbon(功能区)的使用
  16. 案例:用python将中文翻译的和英文原文合成新的word文档
  17. 【嵌入传播】Embedding Propagation: Smoother Manifold for Few-Shot Classification
  18. 在线教育投融数据(2015-2020年)
  19. CSS入门(CSS常用属性----字体、对齐方式、display属性、浮动)
  20. 字符区位码 java_用Java取得汉字的区位码

热门文章

  1. linux下pcap文件解析头文件,在Linux下操作pcap文件的各种方法整理
  2. Spark RDD、DataFrame和DataSet的区别
  3. 临时切换淘宝源下载包
  4. Date实战案例:倒计时日历
  5. DEFCON China倒计时 没想到炸屏“玩坏”百度
  6. iOS - NSURLSession 网络请求
  7. Zabbix安装界面显示PHP time zone 为“红色”的解决办法
  8. 备份一篇SVN的文章, 从搭建到主备库
  9. visual studio 2012如何彻底删除TFS上的团队项目
  10. 小猿圈之测试用例的八大要素