【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】

如果我们需要在将来某个时间点调度执行某个动作,同时在该时间点到达之前不会阻塞当前进程,可以使用内核定时器。内核定时器可用来在未来的某个特定时间点调度执行某个函数,从而可用于完成许多任务。
Linux 内核所提供的用于操作定时器的数据结构和函数(位于 <linux/timer.h>)如下

struct timer_list {/** All fields that change during normal runtime grouped to the* same cacheline*/struct list_head entry;        /* 定时器列表 */unsigned long expires;        /* 期望定时器执行的jiffies值 */struct tvec_base *base;void (*function)(unsigned long);/* 定时器处理函数 */unsigned long data;        /* 作为参数被传入定时器处理函数 */int slack;#ifdef CONFIG_TIMER_STATSint start_pid;void *start_site;char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;
#endif
};

使用定时器必须初始化,使用函数

void init_timer(struct timer_list * timer);

然后还需为定时器结构成员expires、function、data(需要的话)赋值。
使用如下函数注册定时器:

void add_timer(struct timer_list * timer);

这样定时器将在expires之后执行函数function,不过此时只能执行一次,如果想在之后每个expires时间都执行function函数的话,需要在function函数里面修改定时器expires的值。使用如下函数修改:

int mod_timer(struct timer_list *timer, unsigned long expires);

在定时器处理函数中,在做完相应的工作后,往往会延后 expires 并将定时器再次添加到内核定时器链表,以便定时器能再次被触发。

一个示例如下:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>#include <linux/timer.h>
#include <linux/delay.h>struct timer_list   sln_timer;void sln_timer_do(unsigned long l)
{mod_timer(&sln_timer, jiffies + HZ);//HZ为1秒,在此时间之后继续执行printk(KERN_ALERT"jiffies: %ld\n", jiffies);//简单打印jiffies的值
}void sln_timer_set(void)
{init_timer(&sln_timer);//初始化定时器sln_timer.expires = jiffies + HZ;   //1s后执行sln_timer.function = sln_timer_do;    //执行函数add_timer(&sln_timer);    //向内核注册定时器
}static int __init sln_init(void)
{printk(KERN_ALERT"===%s===\n", __func__);sln_timer_set();return 0;
}static void __exit sln_exit(void)
{printk(KERN_ALERT"===%s===\n", __func__);del_timer(&sln_timer);//删除定时器
}module_init(sln_init);
module_exit(sln_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("sln");

像定时器这种周期性的任务还可以使用延时工作队列来实现。
给一个示例:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/version.h>#include <linux/workqueue.h>
#include <linux/delay.h>static struct workqueue_struct      *sln_wq = NULL;
static struct delayed_work          sln_dwq;static void sln_do(struct work_struct *ws)
{queue_delayed_work(sln_wq, &sln_dwq, 1000);printk(KERN_ALERT"jiffies: %ld\n", jiffies);
}static int __init sln_init(void)
{printk(KERN_ALERT"===%s===\n", __func__);sln_wq = create_workqueue("sln_work_queue");INIT_DELAYED_WORK(&sln_dwq, sln_do);queue_delayed_work(sln_wq, &sln_dwq, 0);return 0;
}static void __exit sln_exit(void)
{printk(KERN_ALERT"===%s===\n", __func__);cancel_delayed_work(&sln_dwq);flush_workqueue(sln_wq);destroy_workqueue(sln_wq);
}module_init(sln_init);
module_exit(sln_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("allen");

linux内核编程之内核定时器相关推荐

  1. linux 应用层编程之内核链表list的使用

    linux内核提供了一个经典通用的双向循环链表list的实现,任何模块都可以借助该接口实现自己的内部循环链表.因为是通用的,可以直接移植到用户态中使用,下面介绍相关的接口与一个简单操作例子,包括链表的 ...

  2. linux内核编程_内核线程kthread_run

    linux内核编程_内核线程kthread_run 1. 简述: 2. 使用示例: 3. 详述: 1. 简述: 头文件: include/linux/kthread.h 数据类型: struct ta ...

  3. Linux 环境编程 用户层定时器使用二 timer_create的使用

    用户层定时器有两种,一种是timerfd,另一种是timer_create,前者比较新,使用比较方便. Linux环境编程 用户层定时器使用一 timerfd的使用 https://blog.csdn ...

  4. Win64 驱动内核编程-8.内核里的其他常用

    内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...

  5. Win64 驱动内核编程-3.内核里使用内存

    内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...

  6. Linux环境编程 用户层定时器使用一 timerfd的使用

    timerfd是linux提供的定时器机制,基于文件描述符,定时器精度最高可达纳秒级别,接口包括定时器创建.启动定时器.关闭定时器和删除定时器.下面介绍一下timerfd  API接口和一个结合epo ...

  7. linux内核编程,实现内核之间的调用

    Linux 内核模块编写三个模块文件mainmod.c,lenmod.c,summod.c,在mainmod模块调用summod模块对数组进行求和运算,调用lenmod模块求数组中元素 1 先看自己的 ...

  8. Win64 驱动内核编程-6.内核里操作注册表

    内核里操作注册表 RING0 操作注册表和 RING3 的区别也不大,同样是"获得句柄->执行操作->关闭句柄"的模式,同样也只能使用内核 API 不能使用 WIN32 ...

  9. Win64 驱动内核编程-5.内核里操作文件

    内核里操作文件 RING0 操作文件和 RING3 操作文件在流程上没什么大的区别,也是"获得文件句柄->读/写/删/改->关闭文件句柄"的模式.当然了,只能用内核 A ...

  10. Win64 驱动内核编程-4.内核里操作字符串

    内核里操作字符串 字符串本质上就是一段内存,之所以和内存使用分开讲,是因为内核里的字符串太有花 样了,细数下来竟然有 4 种字符串!这四种字符串,分别是:CHAR*.WCHAR*.ANSI_STRIN ...

最新文章

  1. 洛谷P2286 [HNOI2004]宠物收养所 [STL,平衡树]
  2. python中字典的输出序列_python3:序列_字典(常用基础知识)
  3. 专升本c语言名词解释题_专升本到底难不难?
  4. 执​行​o​r​a​c​l​e​函​数​的​四​种​方​法
  5. python 通过ip获取城市_Python根据用户IP判断所属城市 !
  6. 遍历二叉树(四种方式:前序、中序、后序、层序)
  7. winform的label内容居中_C# Winform label自定义大小与居中实现教程
  8. C++11 thread_local
  9. java jdk 64 1.8_JDK1.8 64位官方下载
  10. 趣图:程序员桌面对比,iOS vs 安卓
  11. Tomcat运行原理
  12. php钱汇算成美元,PHP to USD
  13. ABeam Insight | 女性科技系列(2):全球女性科技(FemTech)现状
  14. MATLAB 机器人工具箱简单教程:(下载及安装)
  15. vue3 滑动验证组件
  16. ARCGIS制作图中图——小图/一幅多图
  17. FCM聚类与K-means聚类的分析比较
  18. Oracle版本升级后引出的catalog连接问题
  19. 【量化交易】94篇论文分析股市预测的深度学习技术
  20. 新GSP质量文件——21个岗位职责

热门文章

  1. mysql 网页_mysql网页客户端工具
  2. C语言 职工信息管理系统
  3. Camera Probe 代码分析
  4. 九款Web服务器性能压力测试工具
  5. 如何完整离线保存网页,包括网页完整特效?
  6. 适合程序员的简历模板
  7. DevCon 5 2019 活动照片
  8. vi编辑器的常用命令
  9. matlab实现QPSK调制解调
  10. 奇怪的技能又增加了,我学会了用ETS5配置KNX