Linux驱动学习—内核定时器

1、内核定时器

1.1 Linux内核定时器概念

不同于单片机定时器,LInux内核定时器是一种基于未来时间点的计时方式,以当前时刻来启动的时间点,以未来的某一时刻为终止点。比如,现在是10点5分,我要定时5分钟,那么定时就是10点5分+5分钟=10点10分。这个和手机闹钟很相似。比如你要定一个第二天早晨8点的闹钟,就是当前时间定时到第二天早晨8点。

需要注意的是,内核定时器定时精度不高,不能作为高精度定时器使用。并且内核定时器并不是周期性运行的,超时以后就会自动关闭,因此如果想要实现周期性定时,那么就需要在定时处理函数中重新开启定时器。

1.2 Linux内核定时器基础知识

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 hlist_node   entry;
    unsigned long       expires;/*定时器超时时间,不是时长,单位是节拍数*/
    void            (*function)(unsigned long);/*定时处理函数*/
    unsigned long       data;/*要传递function函数的参数*/
    u32         flags;
​
#ifdef CONFIG_TIMER_STATS
    int         start_pid;
    void            *start_site;
    char            start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
    struct lockdep_map  lockdep_map;
#endif
};

在上面这个结构体中,有几个参数需要重点关注一下。一个是expires到期时间,单位是节拍数。等于定时的当前的始终节拍计数(存储在系统的全局变量和jiffies)+定时时长对应的时钟节拍数量。

那么如何把时间 转换成节拍数量呢?示例:假如从现在开始定时1秒,转换成节拍数量是多少呢? 内核中有一个宏HZ,表示一秒对应的时钟节拍数,那么我们就可以通过这个宏来把时间转换成节拍数。所以,定时1秒就是expires = jiffies + 1*HZ。

HZ的值我们是可以设置的,也就是一秒对应的时钟拍数我们是可以设置的,Linux内核会使用CONFIG_HZ来设置自己的系统时钟。打开include/asm-generic/param.h,有如下内容:

# undef HZ
# define HZ     CONFIG_HZ   /* Internal kernel timer frequency */
# define USER_HZ    100     /* some user interfaces are */

宏HZ就是CONFIG_HZ,因此HZ=100,表示一秒的节拍数是100,在编译Linux内核的时候可以通过图形化界面设置系统节拍率,按照如下路径打开配置界面。

通过上图我们可以发现可选的系统节拍率为100HZ,200HZ,250HZ,300HZ、500HZ和1000HZ.默认是100HZ。

第二个需要关心的参数是function超时能处理处理函数,这个并不是硬件中断 服务程序。原型:

void function(unsigned long data);

第三个参数是data传递给超时处理函数的参数,可以把一个变量的地址转换成unsigned long。

1.3 Linux内核定时器相关操作函数

1.3.1 时间转换函数
<1>ms转换成时钟节拍函数

在include/linux/jiffies.h

unsigned long msecs_to_jiffies(const unsigned int m);

举例:定时10ms 计算:jiffes+msecs_to_jiffies(10)

<2>us转换成时钟节拍函数
unsigned long usecs_to_jiffies(const unsigned int u);

举例:定时10us 计算:jiffes+usecs_to_jiffies(10)

1.3.2 宏DEFINE_TIMER

在include\linux\timer.h

#define DEFINE_TIMER(_name, _function, _expires, _data)     \
    struct timer_list _name =               \
        TIMER_INITIALIZER(_function, _expires, _data)
参数:_name变量名;__function超时处理函数;_expires到点时间,一般在启动定时前需要重新初始化。

作用:静态定义结构体变量并且初始化function,expires,data成员。

1.3.3 add_timer函数

在include\linux\timer.h

void add_timer(struct timer_list *timer);
参数:timer要注册的定时器。

作用:add_timer函数用于向Linux内核注册定时器,使用add_timer函数向内核注册定时器以后,定时器就会开始运行。

1.3.4 del_timer函数
int del_timer(struct timer_list * timer);
timer:要删除的定时器。
返回值:0,定时器还没被激活;1,定时器已经激活

作用:del_timer函数用于删除一个定时器,不管定时器有没有被激活,都可以使用此函数删除。在多处理器系统上,定时器可能会在其他的处理器运行,因此在调用del_timer函数删除定时器之前要先等待其他处理器的定时处理其函数退出。

1.3.5 mod_timer 函数
int mod_timer(struct timer_list *timer, unsigned long expires);
参数:
timer:要修改超时时间(定时值)的定时器。
expires:修改后的超时时间。
返回值:0,调用mod_timer 函数前定时器违背激活;
       1,调用mod_timer 函数前定时器已被激活

作用:mod_timer 函数用于修改定时值,如果定时器还没有激活的话,mod_timer 函数会激活定时器。

1.4 实验代码

#include <linux/init.h>
#include <linux/module.h>//最基本的文件,支持动态添加和卸载模块
#include <linux/miscdevice.h>//注册杂项设备头文件
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
​
 static void timer_function(unsigned long data);
 
 DEFINE_TIMER(test_timer, timer_function, 0, 0);
 
 static void timer_function(unsigned long data)
 {
    printk("this is timer_function\n");
    mod_timer(&test_timer, jiffies + 1*HZ);
 }
 
​
static int hello_init(void)
{
    test_timer.expires = jiffies + 1 * HZ;
    add_timer(&test_timer);
    return 0;
}
 
static void hello_exit(void)
{
    del_timer(&test_timer);
    printk("hello_exit \n");
}
 
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

2、实验:使用内核定时器实现按键消抖

Linux驱动学习—中断-CSDN博客

在上面链接的按键中断实验代码上修改:

按下按键:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/299842.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java反射和动态代理

文章目录 1、反射1.1 反射的概述1.2 反射作用1.3 获取字节码文件对象的方式1.4 字节码文件和字节码文件对象1.5 获取构造方法1.6 获取构造方法并创建对象1.7 获取成员变量并获取值和修改值1.8 获取成员方法1.9 获取成员方法并运行1.10 反射练习1.10.1 泛型擦除1.10.2 修改字符串…

vue+nodejs微信小程序基于uniapp的学生宿舍打卡失物招领管理系统

基于微信的宿舍管理系统的设计基于现有的手机&#xff0c;可以实现等功能。方便用户对宿舍管理系统查看个人中心、失物招领管理、失物认领管理、晚归打卡管理、宿舍信息管理、宿舍更新管理、交流论坛、系统管理等功能模块的管理及详细的设计与统计分析。根据系统功能需求建立的…

网络安全法解读之思维导图

一、出台背景 二、法律基础 三、网络安全法架构 1、第一章 总则&#xff08;1-14条&#xff09; 2、第二章 网络安全支持与促进&#xff08;15-20条&#xff09; 3、 第三章 网络运行安全&#xff08;21-39条&#xff09; &#xff08;1&#xff09;第一节 一般规定 &#xf…

Linux无法启动:Timed out waiting for device dev-disk-by

由于CPU风扇问题&#xff0c;导致主机无法启动&#xff1b;鉴于机器本身比较老旧&#xff0c;因此&#xff0c;决定直接把硬盘拆下后更换到新的主机上&#xff0c;更安全可靠&#xff1b;问题却因此而起&#xff1a;把硬盘更换到新主机后&#xff0c;居然无法启动&#xff0c;开…

简易机器学习笔记(九)LeNet实例 - 在眼疾识别数据集iChallenge-PM上的应用

前言 上一节大概讲了一下LeNet的内容&#xff0c;这一章就直接来用&#xff0c;实际上用一下LeNet来进行训练和分类试试。 调用的数据集&#xff1a; https://aistudio.baidu.com/datasetdetail/19065 说明&#xff1a; 如今近视已经成为困扰人们健康的一项全球性负担&…

Windows下默认关闭数字键盘

进入注册表&#xff0c;找到值HKEY_USERS 》 .DEFAULT 》 Control Panel 》 Keyboard &#xff0c;点击 Keyboard 之后在右侧窗口中找到 InitialKeyboardIndicators&#xff0c;设置为0&#xff0c;保存&#xff0c;重启电脑 该值的意义

深信服技术认证“SCSA-S”划重点:文件包含漏洞

为帮助大家更加系统化地学习网络安全知识&#xff0c;以及更高效地通过深信服安全服务认证工程师考核&#xff0c;深信服特别推出“SCSA-S认证备考秘笈”共十期内容&#xff0c;“考试重点”内容框架&#xff0c;帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…

永磁同步电机的磁场定向控制

目录 概述 通过系统仿真验证行为 探索模型架构 生成用于集成到嵌入式应用程序的控制器 C 代码 指定控制器模型的参考行为 创建 PIL 实现 准备用于 PIL 测试的控制器模型 测试生成的代码的行为和执行时间 结论 此示例说明从电机控制算法生成 C 代码并验证其编译行为和执…

分布式事务完美解决方案:消息中间件(kafka)+ 本地事物 + 消息校对

前言 分布式事务是要保证多个服务下的多个数据库操作的一致性。分布式事务常见解决方案有&#xff1a;二阶段、三阶段和TCC实现强一致性事务&#xff0c;其实还有一种广为人知的方案就是利用消息队列来实现分布式事务&#xff0c;保证数据的最终一致性&#xff0c;也就是我们常…

带大家做一个,易上手的家常香干炒腊肉

从冰箱那一块腊肉 套个食品级的袋子 然后用冷水化冰 准备两块香干 香干切成片 不要太薄 当然也别厚了 一把青蒜 青蒜切成段 干和叶子分开装 腊肉去掉下面的肉皮 然后切小块 锅中加入清水 下入少量油和盐 开小火 水起泡泡后下入香干 过水 半分钟左右 香干捞出备用 将腊…

Geoserver扩展发布MySQL视图功能

Geoserver中并不自带mysql数据发布功能&#xff0c;需要扩展外部插件。 1、示例以geoserver-2.20.5版本进行演示&#xff0c;所以MySQL插件需要到该版本对应的“Extensions”标题下查找&#xff0c;下载地址&#xff1a;GeoServer&#xff0c;详见下图 2、选择MySQL进入下载页…

【北邮国院大四上】Business Technology Strategy 企业技术战略

北邮国院电商大四在读&#xff0c;本笔记仅为PPT内容的整理与翻译&#xff0c;并不代表本课程的考纲及重点&#xff0c;仅为本人复习时方便阅读与思考之作。 写在前面 大家好&#xff0c;欢迎来到大学期间的最后一门课程&#xff0c;本门课程是中方课&#xff0c;所以很庆幸的…

小微企业在银行信贷相关产品和机器学习建模案例_论文科研_企业调研

各银行小微企业贷款业务 互联网的时代&#xff0c;大量新信息技术的涌现和网络的无处不在&#xff0c;想要抢占这片金融天地&#xff0c;必须重视小微金融业务&#xff0c;小微企业是一直具有重大潜力的客户&#xff0c;商业银行、消金公司发展小微信贷业务可以拓宽自身客户群…

C#编程-显示运算符重载

重载函数的概念也可以应用于运算符。在将C#运算符应用到用户定义的数据类型时,运算符重载为它们提供额外的能力。只可以重载预定义的C#运算符组。 运算符重载的必要性 大多数内置数据类型都有与它们相关的预定义运算符。例如:带有运算符+、-、*和/的C#数据类型int为数学运算…

JavaScript面向对象编程实战

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》 ​ ​ ✨ 前言 面向对象编程(OOP)是JavaScript中非常重要的一个概念。掌握OOP可以帮助我们写出更加清晰、…

synchronized、volatile关键字

Java中的synchronized关键字 synchronized关键字介绍 synchronized块是Java提供的一种原子性内置锁&#xff0c;Java中的每个对象都可以把它当作一个同步锁来使用&#xff0c;这些Java内置的使用者看不到的锁被称为内部锁&#xff0c;也叫作监视器锁。 线程的执行代码在进入…

LLM Agent之RAG的反思:放弃了压缩还是智能么?

已经唠了三章的RAG&#xff0c;是时候回头反思一下&#xff0c;当前的RAG是解决幻觉的终点么&#xff1f;我给不出直接的答案&#xff0c;不过感觉当前把RAG当作传统搜索框架在大模型时代下的改良&#xff0c;这个思路的天花板高度有限~ 反思来源于对RAG下模型回答的直观感受&…

【软考中级-软件设计师】day3:程序设计语言基础知识

概述 练习题 程序设计语言的基本成分 练习题 编译程序基本原理 名词解释 词法分析 词法分析&#xff08;英语&#xff1a;lexical analysis&#xff09;是计算机科学中将字符序列转换为单词&#xff08;Token&#xff09;序列的过程。进行词法分析的程序或者函数叫作…

Duboo-入门到学废【下篇】

目录 &#x1f953;1.dubbo-admin &#x1f32d;2.序列化 &#x1f9c2;3.超时 &#x1f95a;4.重试 ❤️5.多版本 &#x1f9c7;6.负载均衡 &#x1f35f;7.集群容错 1.dubbo-admin &#x1f495;&#x1f495;&#x1f495; 1.1dubbo-admin是什么 1.duboo-admin是一…

【大数据】Flink CDC 的概览和使用

Flink CDC 的概览和使用 1.什么是 CDC2.什么是 Flink CDC3.Flink CDC 前生今世3.1 Flink CDC 1.x3.2 Flink CDC 2.x3.3 Flink CDC 3.x 4.Flink CDC 使用5.Debezium 标准 CDC Event 格式详解 1.什么是 CDC CDC&#xff08;Change Data Capture&#xff0c;数据变更抓取&#xf…
最新文章