Linux内核定时器与延迟工作驱动开发详解
Linux内核定时器与延迟工作是两种常用的实现定时任务和延后执行任务的机制,它们可以让驱动程序在合适的时间点执行特定的函数,以适应硬件设备的需求和特性。但是,如何正确地使用Linux内核定时器与延迟工作呢?本文将从理论和实践两方面,介绍Linux内核定时器与延迟工作驱动开发的基本知识和技巧,以及一些常见的问题和解决方法。
内核定时器
软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行。实际上,时钟中断处理程序会触发TIMER_SOFTIRQ软中断,运行当前处理器上到期的所有定时器。
设备驱动程序如要获得时间信息以及需要定时服务,都可以使用内核定时器。
jiffies
要说内核定时器,首先就得说说内核中关于时间的一个重要的概念:jiffies变量,作为内核时钟的基础,jiffies每隔一个固定的时间就会增加1,称为增加一个节拍,这个固定间隔由定时器中断来实现,每秒中产生多少个定时器中断,由在
//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中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

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

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

启动 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

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

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

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

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

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