在线精品99_中国九九盗摄偷拍偷看_91免费版在线观看_91.app_91高清视频在线_99热最新网站

Linux内核定时器与延迟工作怎么实现

145次阅读
没有评论

共计 2959 个字符,预计需要花费 8 分钟才能阅读完成。

本篇内容介绍了“Linux 内核定时器与延迟工作怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

内核定时器

软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行。实际上,时钟中断处理程序会触发 TIMER_SOFTIRQ 软中断,运行当前处理器上到期的所有定时器。

设备驱动程序如要获得时间信息以及需要定时服务,都可以使用内核定时器。

jiffies

要说内核定时器,首先就得说说内核中关于时间的一个重要的概念:jiffies 变量,作为内核时钟的基础,jiffies 每隔一个固定的时间就会增加 1, 称为增加一个节拍,这个固定间隔由定时器中断来实现,每秒中产生多少个定时器中断,由在 linux/param.h 中定义的 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 /** * do_gettimeofday - Returns the time of day in a timeval * @tv: pointer to the timeval to be set * * NOTE: Users should be converted to using getnstimeofday() */ 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 struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func; #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; struct delayed_work { 114 struct work_struct work; struct timer_list timer; /* target workqueue and CPU - timer uses to queue - work */ struct workqueue_struct *wq; int cpu; };

–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 内核定时器与延迟工作怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计2959字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)
主站蜘蛛池模板: 99er这里只有精品 | 青青青国产深夜福利视频 | 最近中文字幕高清字幕在线视频 | 精品久久一区二区 | 日本黄色三级网站 | 亚洲av日韩专区在线观看 | 高清在线亚洲精品国产二区 | 欧美丰满老妇性猛交 | 国产精品美女久久久久网站 | 国产精品欧美一区二区三区不卡 | 国产丝袜免费视频网址 | 免费日韩视频 | 日韩福利视频 | 国内精品久久久久影院6 | 国产日韩一区二区 | 亚洲精品欧美综合 | 能在线观看的一区二区三区 | 夜夜高潮夜夜爽夜夜爱爱 | 亚洲欧美在线视频免费 | 精品女同一区二区三区在线观看 | 九九视频免费看 | 333kkkkk欧美在线观看 | 黄色一级在线 | 亚洲成人午夜影院 | 风韵丰满熟妇啪啪区老老熟妇 | 国产精品视频你懂的 | 大肉大捧一进一出视频出来呀 | 国产欧美日韩精品综合 | 精品国产一区二区二三区在线观看 | 一 级 黄 色 片免费网站 | 婷婷开心激情综合五月天 | 青青青免费网站在线观看 | 国产欧美久久久另类精品 | 亚洲精品久久久久久久不卡四虎 | 少妇人妻精品一区二区 | 乱精品一区字幕二区 | 中文字幕在线一区 | 日本精品视频在线 | 国产精品一区二区三区免费视频 | 亚洲av无码日韩av无码导航 | 国产精品99精品无码视亚 |