ktime_t结构
相对timer定时器,hrtimer是以ktime_t来定义时间的。ktime_t的结构如下所示:
union ktime {
s64 tv64;
};
typedef union ktime ktime_t; /* Kill this */
ktime_t是一个64位的数,针对ktime_t有如下的一些函数(更多的代码请查看include/linux/ktime.h)
ktime_t ktime_set(secs, nsecs) : 初始化一个ktime_t对象
ktime_t ktime_get() : 获取系统自启动以来的相对时间
ktime_t ktime_get_real() : 获取系统真实时间
struct timeval ktime_to_timeval(ktime_t kt)
struct timespec ktime_to_timespec(ktime_t kt)
ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
ktime_after(const ktime_t cmp1, const ktime_t cmp2)
ktime_before(const ktime_t cmp1, const ktime_t cmp2)
hrtimer结构体
struct hrtimer {
....
enum hrtimer_restart (*function)(struct hrtimer *);
....
};
hrtimer结构体中对驱动开发者有用的成员为function,通过function成员指定hrtimer定时器函数,其返回为枚举值hrtimer_restart,如果在定时器函数中重新设置定时器,实现延时或者循环,可以返回HRTIMER_RESTART告诉内核重启定时器。
/*
* Return values for the callback function
*/
enum hrtimer_restart {
HRTIMER_NORESTART, /* Timer is not restarted */
HRTIMER_RESTART, /* Timer must be restarted */
};
hrtimer定时器常用函数
//hrtimer_init初始化一个hrtimer,clock_id是时钟类型,CLOCK_MONOTONIC表示自系统开机以来的单调递增时间,
//mode是时间模式,HRTIMER_MODE_ABS表绝对时间,HRTIMER_MODE_REL表相对时间
hrtimer_init(struct hrtimer *timer, clockid_t clock_id , enum hrtimer_mode mode)
//初始化之后就可以调用以下两个函数开始定时器,
//hrtimer_forward_now设置的时间为距离当前的interval个时间后
hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
hrtimer_forward_now(struct hrtimer *timer,ktime_t interval)
//取消函数
hrtimer_cancel(struct hrtimer *timer)
hrtimer实践
纸上谈兵没用,本萌觉得学习驱动,可能最好的方法是多写,多搞点乱七八糟的需求让自己去学着实现,将这些文绉绉的知识变为实实在在的代码,在不知道怎么写的时候,在内核源代码中都有相应的实现。好记性不如烂笔头嘛,自己安慰自己,哈哈哈。
需求
①设置定时器时间为10ms
②驱动每10ms生成一个uuid,并保存定时器函数被调用的ktime_t时间,一共生成5个uuid,即要设置5次定时器。
③通过cat /proc/test_proc可以查看到相应的uuid和ktime_t时间,生成ktime_t时间是为了通过实验查看定时器调用的精度。
④通过seq_file接口,实现其中的start,next,show,stop方法,使用链表组织以上的uuid数据和ktime_t时间。
最终效果如下图(可以看到该高精度计时器有一定误差)

代码说明
可以跳到最后看代码,本萌希望求得各位大佬的批评意见,这里写代码说明,一是为了防止遗忘,一是为了讲述代码的实现过程。
其实,之所以要刻意用链表把数据组织起来,是因为我的上一篇文章写timer定时器的时候,将所有数据直接扔到内存页中,简单粗暴但空间浪费得有点多。所以这里我想总结下链表的用法(毕竟这篇文章是写给我自己看的嘛)。
//链表初始化:
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
//链表的插入(有两个函数list_add和list_add_tail),本质上都是调用_list_add方法
//__list_add(new, A, B);
//查看代码发现_list_add就是将新的节点插入到A和B节点之间
//list_add将new插入到head和head->next之间,即新插入的节点

本文详细介绍了Linux内核中的高精度定时器(hrtimer)原理与应用,包括ktime_t结构、hrtimer结构及函数。通过具体实例,展示了如何使用hrtimer设置定时任务,每10ms生成一个UUID并记录时间,最后通过proc文件系统展示结果。
最低0.47元/天 解锁文章
364

被折叠的 条评论
为什么被折叠?



