一、内核定时器简介:

Linux 内核定时器使用很简单,只需要提供超时时间(相当于当前时刻)和定时处理函数即可,当超时时间到了以后设置的定时处理函数就会执行。在使用内核定时器的时候要注意一点,内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那么就需要在定时处理函数中重新开启定时器。

二、几个基础概念

linux系统上,有两个非常重要的时间,墙上时间和系统运行时间。

系统运行时间:自系统启动开始所经过的时间

墙上时间:指当前时刻,可以通过ntp服务器获取,获取后可以结合系统运行时间进行本地更新。

那么linux是怎么计算系统运行时间的呢?

答:由cpu内部定时器提供时钟源,时钟源的频率可以设置,设置好以后就周期性的产生定时中断(这个中断叫做系统定时器中断),每进入一次中断就可以累加一次时间。

note:注意区分系统定时器和内核定时器的概念,内核定时器是依赖于系统定时器的。

1、节拍率:HZ

系统定时器频率(节拍率)是在<include/asm-generic/param.h>文件中定义的,也就是HZ。

#ifndef __ASM_GENERIC_PARAM_H
#define __ASM_GENERIC_PARAM_H#ifndef HZ
#define HZ 100
#endif#ifndef EXEC_PAGESIZE
#define EXEC_PAGESIZE   4096
#endif#ifndef NOGROUP
#define NOGROUP     (-1)
#endif#define MAXHOSTNAMELEN    64  /* max length of hostname */#ifdef __KERNEL__
# undef HZ
# define HZ     CONFIG_HZ   /* CONFIG_HZ是通过menuconfig配置的产物 */
# define USER_HZ    100     /* some user interfaces are */
# define CLOCKS_PER_SEC (USER_HZ)       /* in "ticks" like times() */
#endif#endif /* __ASM_GENERIC_PARAM_H */

在系统启动时按照HZ值对硬件进行设置(怎么设置的?)。

一般 ARM 体系结构的节拍率多数都等于 100。在编译 Linux 内核的时候可以通过图形化界面

设置系统节拍率,按照如下路径打开配置界面:

-> Kernel Features
-> Timer frequency (<choice> [=y])

2、jiffies全局变量

全局变量 jiffies 用来记录自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为 0,此后,每次时钟中断处理程序都会增加该变量的值。因为一秒内时钟中断的次数等于 Hz,所以 jiffes 一秒内增加的值也就为 Hz,系统运行时间以秒为单位计算,就等于 jiffes/Hz。jiffes=seconds*HZ。jiffies 定义在文件include/linux/jiffies.h 中,定义如下:

extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

因此,在 32 位体系结构上jiffies 是 32 位,在时钟频率为 100 的情况下,497 天后会溢出,如果频率是 1000,49.7 天后会溢出。溢出后,它的值会回绕到 0。回绕会引起许多问题,下面的宏可以正确的处理节拍计数回绕的情况:

三、相关数据结构和API

1、数据结构

Linux 内核使用 timer_list 结构体表示内核定时器, timer_list 定义在文件include/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;                    /* 定时器超时时间,单位是节拍数 */struct tvec_base *base;void (*function)(unsigned long);      /* 定时处理函数 */unsigned long data;                     /* 要传递给 function 函数的参数 */int slack;#ifdef CONFIG_TIMER_STATSint start_pid;void *start_site;char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;
#endif
};
  • entry:所有的定时器都会根据到期的时间被分配到一组链表中的一个中,该字段是链表的节点成员。
  • expires:字段指出了该定时器的到期时刻,也就是期望定时器到期时刻的jiffies计数值。这是一个绝对值,不是距离当前时刻再过多少jiffies。
  • function:是一个回调函数指针,定时器到期时,系统将会调用该函数,用于响应该定时器的到期事件。
  • data:要传递给 function 函数的参数

2、API

如果需要在定时器超时前停止定时器,可以使用del_timer()函数,如果定时器还未被激活该函数返回0,否则返回1。不需要为已经超时的定时器使用该函数,因为它们会自动删除。

当删除定时器时,必须注意一个潜在的竞争条件,当del_timer()返回后,可以保证的只有定时器不会再被激活,但是在多处理器机器上定时器中断可能已经在其他处理器上运行了,所以删除定时器时需要等待可能在其他处理器上运行的定时器处理程序都退出,这时就要使用del_timer_sync()函数执行删除工作,和del_timer()函数不同,del_timer_sync()函数不能在中断上下文中使用。

从4.14 Linux内核开始使用带有三个args的timer_setup()替换掉之前的init_timer();

四、简单使用

#include <linux/timer.h>
#include <linux/jiffies.h>struct timer_list timer; /* 定义定时器 *//* 定时器回调函数 */
void function(unsigned long arg)
{/** 定时器处理代码*//* 如果需要定时器周期性运行的话就使用 mod_timer 11 * 函数重新设置超时值并且启动定时器。*/ mod_timer(&timer, jiffies + msecs_to_jiffies(2000));}/* 初始化函数 */
void init(void)
{init_timer(&timer); /* 初始化定时器 */timer.function = function; /* 设置定时处理函数 */timer.expires=jiffies + msecs_to_jiffies(2000);/* 设置超时时间 2 秒 *///timer.data = arg; /* 给回调函数传入参数 */add_timer(&timer); /* 启动定时器 */
}/* 退出函数 */
void exit(void)
{del_timer(&timer); /* 删除定时器 *//* 或者使用 *///del_timer_sync(&timer);
}

ref:

Linux 内核定时器 - sudochen - 博客园

Linux内核定时器简介及其简单使用_一只青木呀的博客-CSDN博客_linux 定时器

LInux内核定时器_月如风清的博客-CSDN博客_linux内核定时器实现

linux内核中使用定时器_Legendary_wasper的博客-CSDN博客

内核定时器API之timer_setup | DD'Notes

c - Adaptation from old init_timer to new timer_setup - Stack Overflow

3.10.1. linux内核定时器 — ywg_dev_doc 0.1 文档

源码分析

Linux内核定时器和工作队列的总结和实例 - 简书

linux 内核 定时器(timer)实现机制_老王不让用的博客-CSDN博客_linux timer 内核

linux内核定时器相关推荐

  1. Linux 内核定时器实验————复习到这

    目录 Linux 时间管理和内核定时器简介 内核时间管理简介 内核定时器简介 Linux 内核短延时函数 硬件原理图分析 实验程序编写 修改设备树文件 定时器驱动程序编写 编写测试APP 运行测试 编 ...

  2. linux内核定时器编程

    1.linux内核定时器基本结构和函数 1)struct timer_list 一个struct timer_list对应了一个定时器. #include <linux/timer.h> ...

  3. 如何使用 Linux 内核定时器

    1. Linux内核定时器介绍 1.1 内核时间管理 内核中很多函数需要时间管理,比如周期性的调度程序.延时程序.定时器.硬件定时器提供时钟源,时钟源频率可以设置,设置好后就周期性的产生定时中断,系统 ...

  4. linux 内核定时器(低精度) — 外部看门狗程序

    文章目录 1 内核定时器介绍 2 定时器数据结构及函数 3 外部看门狗驱动使用定时器函数 1 内核定时器 Linux 内核中有大量的函数需要时间管理,比如周期性的调度程序.延时程序等.硬件定时器 提供 ...

  5. linux内核定时器实验

    文章目录 一.linux时间管理和内核定时器简介 1.内核时间管理简介 2.内核定时器简介 1.init_timer 函数 2.add_timer 函数 3.del_timer 函数 4.del_ti ...

  6. linux 内核定时器 3.11 版本,Linux内核定时器简单使用

    因为项目需要,我这里简单列一个在内核中使用timer的方法.这篇笔记不谈详细原理(以后的Linux内核设备驱动原理里讲),只讲快速使用 Timer使用原则 Timer是Linux内核的一种软中断,被调 ...

  7. Linux 内核定时器使用 二 高精度定时器 hrtimer 的用例

    之前介绍了timer_list内核定时器,它的精度在毫秒级别,再高一点它就无能为力了,所幸内核提供了高精度定时器 hrtimer. 源文件在linux/kernel/hrtimer.c中.接口简单.下 ...

  8. Linux 内核定时器使用 一 低精度定时器

    内核定时器是一个数据结构,它告诉内核在用户定义的时间点使用用户定义的参数来执行一个用户定义的函数.其实现位于 <linux/timer.h>中. 内核提供了一组用来声明.注册和删除内核定时 ...

  9. (十二)linux内核定时器

    目录 (一)内核定时器介绍 (二)内核定时器相关接口 (三)使用步骤 (四)实例代码 (一)内核定时器介绍 内核定时器并不是用来简单的定时操作,而是在定时时间后,触发事件的操作,类似定时器中断,是内核 ...

  10. linux 内核定时器精度_高精度时钟工作机制简介

    1. 为什么会有高精度时钟 既然提到高精度,那么其对应的就是低精度,所以高精度时钟是为了解决低精度时钟计时精度不足的问题.举个例子帮助理解,日出而作,日落而息,古人以天为单位,安排劳作和休息.随着生产 ...

最新文章

  1. 使用Javascript制作连续滚动字幕
  2. [原创]K8域控植入脚本生成器(内网渗透/RPC不可用解决方案)
  3. scanf函数和cin的区别、类的数组、C++排序函数
  4. java实现短信上行源码_Java 发送短信验证码 示例源码
  5. 项目案例模板之登录注册的实现
  6. ai作文批改_每日即评 | 积极适应“AI批改作文”的潮流
  7. 北京交通大学离散数学 谓词逻辑_离散数学_北京交通大学_中国大学MOOC(慕课)
  8. 如何对QQ好友的IP地址进行精准定位
  9. 单点登录系统和传统登录的区别
  10. python中的snip用法_Ubuntu系统中安装SNIP
  11. 从零到卓越:京东客服即时通讯系统的技术架构演进历程(转)
  12. Php货币计算怎么样才严谨,php怎样【货币问答】- php怎样所有答案 - 联合货币
  13. 微信表情《程序员小黄第二季》上架啦!
  14. 词云中去重复的词_为什么要避免标题关键词重复?
  15. os.rename和os.renames区别
  16. 迷你英雄无限服务器没了吗,迷你英雄:无限无法连接服务器是什么原因
  17. 和老板比,员工弱爆了
  18. [SCOI2007]降雨量 线段树和区间最值(RMQ)问题
  19. matlab中拉式域转时间域,Bark域介绍和线性频率域转换到Bark域
  20. ICSharpCode.SharpZipLib压缩解压

热门文章

  1. 服务器怎么装虚拟打印机,pdfFactory pdf虚拟打印机安装使用教程[图文]
  2. 电路matlab仿真,电路matlab仿真.doc
  3. Linux中常用查看日志命令
  4. C语言实现FFT算法
  5. 病毒木马查杀实战第025篇:JS下载者脚本木马的分析与防御
  6. 配置你的ASP.NET运行环境
  7. 自学c语言需要什么要求,学习c语言需要什么基础
  8. 烟雾检测传感器实验-传感器原理及应用实验
  9. rmvb 转 avi 方法
  10. 计算机制图的基本知识和技能,《计算机绘图基础》制图的基本知识和技能精讲.ppt...