目录
内核定时器" >内核定时器
jiffies" >jiffies
定时器" >定时器
实例" >实例
延迟工作" >延迟工作
首页 系统教程 操作系统 Linux内核定时器与延迟工作驱动开发详解

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

Feb 13, 2024 am 11:57 AM
linux linux教程 linux系统 linux命令 外壳脚本 typedef overflow 嵌入式linux linux入门 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领域的进一步学习和工作打下坚实的基础。

以上是Linux内核定时器与延迟工作驱动开发详解的详细内容。更多信息请关注PHP中文网其他相关文章!

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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Linux实际上有什么好处? Linux实际上有什么好处? Apr 12, 2025 am 12:20 AM

Linux适用于服务器、开发环境和嵌入式系统。1.作为服务器操作系统,Linux稳定高效,常用于部署高并发应用。2.作为开发环境,Linux提供高效的命令行工具和包管理系统,提升开发效率。3.在嵌入式系统中,Linux轻量且可定制,适合资源有限的环境。

将Docker与Linux一起使用:综合指南 将Docker与Linux一起使用:综合指南 Apr 12, 2025 am 12:07 AM

在Linux上使用Docker可以提高开发和部署效率。1.安装Docker:使用脚本在Ubuntu上安装Docker。2.验证安装:运行sudodockerrunhello-world。3.基本用法:创建Nginx容器dockerrun--namemy-nginx-p8080:80-dnginx。4.高级用法:创建自定义镜像,使用Dockerfile构建并运行。5.优化与最佳实践:使用多阶段构建和DockerCompose,遵循编写Dockerfile的最佳实践。

apache怎么启动 apache怎么启动 Apr 13, 2025 pm 01:06 PM

启动 Apache 的步骤如下:安装 Apache(命令:sudo apt-get install apache2 或从官网下载)启动 Apache(Linux:sudo systemctl start apache2;Windows:右键“Apache2.4”服务并选择“启动”)检查是否已启动(Linux:sudo systemctl status apache2;Windows:查看服务管理器中“Apache2.4”服务的状态)启用开机自动启动(可选,Linux:sudo systemctl

apache80端口被占用怎么办 apache80端口被占用怎么办 Apr 13, 2025 pm 01:24 PM

当 Apache 80 端口被占用时,解决方法如下:找出占用该端口的进程并关闭它。检查防火墙设置以确保 Apache 未被阻止。如果以上方法无效,请重新配置 Apache 使用不同的端口。重启 Apache 服务。

oracle怎么启动监听 oracle怎么启动监听 Apr 12, 2025 am 06:00 AM

启动 Oracle 监听器的步骤如下:检查监听器状态(使用 lsnrctl status 命令)对于 Windows,在 Oracle Services Manager 中启动 "TNS Listener" 服务对于 Linux 和 Unix,使用 lsnrctl start 命令启动监听器运行 lsnrctl status 命令验证监听器是否已启动

如何在Debian上监控Nginx SSL性能 如何在Debian上监控Nginx SSL性能 Apr 12, 2025 pm 10:18 PM

本文介绍如何在Debian系统上有效监控Nginx服务器的SSL性能。我们将使用NginxExporter将Nginx状态数据导出到Prometheus,再通过Grafana进行可视化展示。第一步:配置Nginx首先,我们需要在Nginx配置文件中启用stub_status模块来获取Nginx的状态信息。在你的Nginx配置文件(通常位于/etc/nginx/nginx.conf或其包含文件中)中添加以下代码段:location/nginx_status{stub_status

Debian系统中如何设置回收站 Debian系统中如何设置回收站 Apr 12, 2025 pm 10:51 PM

本文介绍两种在Debian系统中配置回收站的方法:图形界面和命令行。方法一:使用Nautilus图形界面打开文件管理器:在桌面或应用程序菜单中找到并启动Nautilus文件管理器(通常名为“文件”)。找到回收站:在左侧导航栏中寻找“回收站”文件夹。如果找不到,请尝试点击“其他位置”或“计算机”进行搜索。配置回收站属性:右键点击“回收站”,选择“属性”。在属性窗口中,您可以调整以下设置:最大大小:限制回收站可用的磁盘空间。保留时间:设置文件在回收站中自动删除前的保

apache服务器怎么重启 apache服务器怎么重启 Apr 13, 2025 pm 01:12 PM

要重启 Apache 服务器,请按照以下步骤操作:Linux/macOS:运行 sudo systemctl restart apache2。Windows:运行 net stop Apache2.4 然后 net start Apache2.4。运行 netstat -a | findstr 80 检查服务器状态。

See all articles