hrtimer小记

 入正题,其实在arch下加入硬件相关的高精度时钟代码并不复杂,不过这个概念倒是让我费了不少力气,前几天的文档丢失事件也在其中。

 

Q:老结构的timer框架能用,为什么还要用hrtimer?

A:相对old来说比较new,比较帅。

 

Q:真的能高精度吗?以前不行吗?

A:能否高精度取决硬件的时钟源,也就是内核需要一个 clock source,这个的精度决定了你的精度,你的精度是秒,你别想提供纳秒的精度。hrtimer一直强调的纳秒概念,也是说他的工作方式是以这个单位来的。以前也不能说是不行,以前工作是基于tick,对于高精度的用户很难使用。或者说,代码比较难统一,这台机器tick是1s,另一台机器tick是1ms,就会有问题了吧。

 

Q:抽象?

A:只说这个hrtimer,他提出一个比较有意思的概念,就是“下一次中断事件到来”,即next event发生时。老的时钟框架,时钟中断是tick时就来,假设,我需要一个5s的定时,但是tick是1s 1000下,那么就会来5000次中断,期间也没啥好干的,不好了吧。现在的情况就不一样了,可以动态设定这个时钟中断什么时候来,也就是5s后来,那么就会来一次中断,好像很好。怎么说抽象呢?其实,这些都是hrtimer抽象出的,实现者并不需要很多处理,即代码,实现 clock source 和 clock event device的几个接口就好了,相对以前,确实是少了,而且这是统一的代码,已经很少硬件相关了。

 

Q:接口:

A:主要是

           clock source 中的 read(), 用来调整系统时间,计算系统时钟,这也是高精度源。

           clock event device中的 set_mode() 和 set_next_event(),前者设置模式,后者则是关键的设置下一次事件到达时间。

 

Q:没有那些模式寄存器能用这个吗?

A:可以的,其实是一样的。 arm 的定时器寄存器可以设置工作模式,periodic / one-shot,和内核代码的定义一样,果然是他们的东西。one-shot模式有个特点,当计数器减到0后,定时器就不动了,也不会有中断了,和名字一样。但我们的定时器没那么高级,没有这些模式供选择,也就是说,计数器减到0仍然会有中断,那不就需要手动关闭中断了吗?不用,为什么呢?hrtimer保证了。

 

又是一篇废话,不过确实在上面耽误了些时间,本来以为把原理看完就能写出了的,写完后感觉和其他arch的代码很接近了,运行程序发现,时间不对,定1s怎么好像是0.1s。。。最后发现,尽然是 clock source 的 read(),需要保证递增,我竟然设反了,这也是无意中发现的,要不我现在还在弄这个不能再改的东西了。

 

如果文档没丢,还可以贴出来大家分享下,可惜了。

 

### Linux 高分辨率定时器 (hrtimer) 的使用方法 #### 初始化高分辨率定时器 为了创建并初始化一个高分辨率定时器,在定义结构体 `struct hrtimer` 后需调用 `hrtimer_init()` 函数来完成初始化工作。此函数接受三个参数:指向定时器对象的指针、时钟ID以及模式。 ```c #include <linux/hrtimer.h> #include <linux/ktime.h> static struct hrtimer my_timer; // 在模块加载或其他适当位置执行初始化 void init_my_hrtimer(void){ hrtimer_init(&my_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); } ``` #### 设置定时周期 设定具体的超时期间可以通过变量 `ktime_t` 来指定,该类型允许表达纳秒级别的精度。对于相对时间间隔来说,通常会利用宏如 `ns_to_ktime()`, 或者直接构建 `timespec` 结构再转换成 `ktime_t`. ```c #define TIMEOUT_NS 1000000 /* 超时时间为1ms */ int set_timeout(void){ ktime_t kt; kt = ns_to_ktime(TIMEOUT_NS); return hrtimer_start(&my_timer, kt, HRTIMER_MODE_REL)[^2]; } ``` #### 注册回调函数 当定时到期后触发的动作由用户自定义的一个回调函数负责处理。这个函数应该遵循特定签名,并且需要在初始化阶段通过设置定时器成员 `.function` 给定。 ```c enum hrtimer_restart my_callback(struct hrtimer *timer){ printk(KERN_INFO "Timer expired\n"); // 可能再次启动定时器或者其他逻辑... return HRTIMER_NORESTART; // 返回值决定是否重启计数 } void setup_timer_function(void){ my_timer.function = &my_callback; } ``` #### 停止定时器 如果不再需要某个正在运行中的定时器,则应当及时停止它以防意外行为发生。这可通过简单的 `hrtimer_cancel()` 实现。 ```c void stop_my_hrtimer(void){ hrtimer_cancel(&my_timer); } ``` 上述代码片段展示了如何在一个Linux驱动程序上下文中操作高分辨率定时器[^4]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值