0

0

Linux内核定时器与延迟工作驱动开发详解

WBOY

WBOY

发布时间:2024-02-13 11:57:24

|

1205人浏览过

|

来源于良许Linux教程网

转载

linux内核定时器与延迟工作是两种常用的实现定时任务和延后执行任务的机制,它们可以让驱动程序在合适的时间点执行特定的函数,以适应硬件设备的需求和特性。但是,如何正确地使用linux内核定时器与延迟工作呢?本文将从理论和实践两方面,介绍linux内核定时器与延迟工作驱动开发的基本知识和技巧,以及一些常见的问题和解决方法。

Linux内核定时器与延迟工作驱动开发详解

内核定时器

软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行。实际上,时钟中断处理程序会触发TIMER_SOFTIRQ软中断,运行当前处理器上到期的所有定时器。
设备驱动程序如要获得时间信息以及需要定时服务,都可以使用内核定时器。

jiffies

要说内核定时器,首先就得说说内核中关于时间的一个重要的概念:jiffies变量,作为内核时钟的基础,jiffies每隔一个固定的时间就会增加1,称为增加一个节拍,这个固定间隔由定时器中断来实现,每秒中产生多少个定时器中断,由在中定义的HZ宏来确定,如此,可以通过jiffies获取一段时间,比如jiffies/HZ表示自系统启动的秒数。下两秒就是(jiffies/HZ+2),内核中用jiffies来计时,秒转换成的jiffies:seconds*HZ,所以以jiffiy为单位,以当前时刻为基准计时2秒:(jiffies/HZ+2)*HZ=jiffies+2*HZ如果要获取当前时间,可以使用**do_gettimeofday()**,该函数填充一个struct timeval结构,有着接近微妙的分辨率。

//kernel/time/timekeeping.c
 473 /**
 474  * do_gettimeofday - Returns the time of day in a timeval
 475  * @tv:         pointer to the timeval to be set
 476  *
 477  * NOTE: Users should be converted to using getnstimeofday()
 478  */
 479 void do_gettimeofday(struct timeval *tv)   

驱动程序为了让硬件有足够的时间完成一些任务,常常需要将特定的代码延后一段时间来执行,根据延时的长短,内核开发中使用长延时短延时两个概念。长延时的定义为:延时时间>多个jiffies,实现长延时可以用查询jiffies的方法:

time_before(jiffies, new_jiffies);
time_after(new_jiffiesmjiffies);

**短延时的定义为:延迟事件接近或短于一个jiffy,实现短延时可以调用

udelay();
mdelay();

这两个函数都是忙等待函数,大量消耗CPU时间,前者使用软件循环来延迟指定数目的微妙数,后者使用前者的嵌套来实现毫秒级的延时。

定时器

驱动可以注册一个内核定时器,来指定一个函数在未来某个时间来执行。定时器从注册到内核开始计时,达到指定的时间后会执行注册的函数。即超时值是一个jiffies值,当jiffies值大于timer->expires时,timer->function就会被执行。API如下

//定一个定时器
struct timer_list my_timer;

//初始化定时器
void init_timer(struct timer_list *timer);
mytimer.function = my_function;
mytimer.expires = jiffies +HZ;

//增加定时器
void add_timer(struct timer_list *timer);

//删除定时器
int del_tiemr(struct timer_list *timer);

实例

static struct timer_list tm;
struct timeval oldtv;

void callback(unsigned long arg)
{
    struct timeval tv;
    char *strp = (char*)arg;
    do_gettimeofday(&tv);
    printk("%s: %ld, %ld\n", __func__,
        tv.tv_sec - oldtv.tv_sec,
        tv.tv_usec- oldtv.tv_usec);
    oldtv = tv;
    tm.expires = jiffies+1*HZ;
    add_timer(&tm);
}

static int __init demo_init(void)
{
    init_timer(&tm);
    do_gettimeofday(&oldtv);
    tm.function= callback;
    tm.data    = (unsigned long)"hello world";
    tm.expires = jiffies+1*HZ;
    add_timer(&tm);
    return 0;
}

延迟工作

除了使用内核定时器完成定时延迟工作,Linux内核还提供了一套封装好的”快捷方式”-delayed_work,和内核定时器类似,其本质也是利用工作队列和定时器实现,

快剪辑
快剪辑

国内⼀体化视频⽣产平台

下载
//include/linux/workqueue.h
100 struct work_struct {           
101         atomic_long_t data;
102         struct list_head entry;
103         work_func_t func;
104 #ifdef CONFIG_LOCKDEP
105         struct lockdep_map lockdep_map;
106 #endif
107 };
113 struct delayed_work {              
114         struct work_struct work;
115         struct timer_list timer;
116 
117         /* target workqueue and CPU ->timer uses to queue ->work */
118         struct workqueue_struct *wq;
119         int cpu;
120 };

struct work_struct
–103–>需要延迟执行的函数, typedef void (work_func_t)(struct work_struct work);

至此,我们可以使用一个delayed_work对象以及相应的调度API实现对指定任务的延时执行

//注册一个延迟执行
591 static inline bool schedule_delayed_work(struct delayed_work *dwork,unsigned long delay)
//注销一个延迟执行
2975 bool cancel_delayed_work(struct delayed_work *dwork)    

和内核定时器一样,延迟执行只会在超时的时候执行一次,如果要实现循环延迟,只需要在注册的函数中再次注册一个延迟执行函数。

schedule_delayed_work(&work,msecs_to_jiffies(poll_interval));

本文从理论和实践两方面,详细介绍了Linux内核定时器与延迟工作驱动开发的基本知识和技巧。我们首先了解了Linux内核定时器与延迟工作的概念、原理、特点和API函数,然后学习了如何使用Linux内核定时器与延迟工作来实现按键事件的检测和处理。最后,我们介绍了一些在Linux内核定时器与延迟工作驱动开发过程中可能遇到的问题,以及相应的解决方法。

通过本文,我们希望能够帮助你掌握Linux内核定时器与延迟工作驱动开发的基本方法和技巧,为你在嵌入式Linux领域的进一步学习和工作打下坚实的基础。

相关文章

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

107

2023.09.26

c语言typedef的用法
c语言typedef的用法

c语言typedef的用法有定义基本类型别名、定义结构体别名、定义指针类型别名、定义枚举类型别名、定义数组类型别名等。本专题为大家提供typedef相关的文章、下载、课程内容,供大家免费下载体验。

96

2023.09.26

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

175

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

97

2025.11.27

function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

476

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

163

2023.10.07

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1348

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

701

2023.06.29

C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

3

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.2万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号