简介
随着内核不断更新演进,内核对定时器的分辨率要求越来越高。硬件的高速发展也逐渐能够满足内核的这一要求,因此内核针对硬件提供的便利,开始设计了更高分辨率的定时器(hrtimer),可达到ns级别。本文主要讲解如何使用高精度定时器。
更多介绍详见内核文档目录kernel/Documentation/timers/hrtimers.txt
数据结构
代码语言:javascript复制/**
* 定时器调用标志位
*/
enum hrtimer_restart {
HRTIMER_NORESTART, /* Timer is not restarted */
HRTIMER_RESTART, /* Timer must be restarted */
};
/**
* struct hrtimer - 基本的hrtimer结构
* @node:timerqueue节点,它也管理node.expires,
* 计时器内部的绝对到期时间
* 表示形式。时间与时钟有关
* 计时器基于的。通过添加进行设置
* 松弛到_softexpires值。对于非范围计时器
* 与_softexpires相同。
* @_softexpires:hrtimer的绝对最早到期时间。
* 计时器的到期时间
* 武装。
* @function: 计时器到期回调函数
* @base: 指向计时器基础的指针(每个cpu和每个时钟)
* @state: 状态信息(请参见上面的位值)
* @is_rel: 设置计时器
* @start_pid:计时器统计信息字段,用于存储任务的pid
* 启动计时器
* @start_site:计时器统计信息字段,用于存储计时器所在的站点
* 开始了
* @start_comm:计时器统计信息字段,用于存储其中的进程名称
* 启动计时器
*
* hrtimer结构必须由hrtimer_init()初始化
*/
struct hrtimer {
struct timerqueue_node node;
ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
u8 state;
u8 is_rel;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
};
使用流程
a.定义定时器结构体变量
代码语言:javascript复制static struct hrtimer task1_timer;
b.初始化定时器任务
代码语言:javascript复制hrtimer_init(&task1_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
task1_timer.function = task1_timer_func;
c.实现定时器回调
代码语言:javascript复制static enum hrtimer_restart task1_timer_func(struct hrtimer *timer)
{
queue_work(test1_workqueue, &test1_item);
hrtimer_start(&task1_timer, ktime_set(2, 0), HRTIMER_MODE_REL); // 2s
return HRTIMER_NORESTART;
}
d.开启定时器
代码语言:javascript复制hrtimer_cancel(&task1_timer);
/* ktime_set第一个参数为秒单位,第二个参数为纳秒,定时时间0s 900000000ns */
hrtimer_start(&task1_timer, ktime_set(0, 900000000), HRTIMER_MODE_REL);
注意事项
(1) 在需要调用开启函数hrtimer_start,先调用hrtimer_cancel将定时器关闭。避免定时器被被开启两次,导致bug。
(2) 重复调用定时器可以在定时器回调函数,返回值返回HRTIMER_RESTART。也可以重新调用hrtimer_start,返回HRTIMER_NORESTART。
(3) 只需要重复执行指定次数,实现方法(举其中一种):
代码语言:javascript复制int i = 0, num = 4;
static enum hrtimer_restart task1_timer_func(struct hrtimer *timer)
{
if(i < num) {
i ;
queue_work(test1_workqueue, &test1_item);
hrtimer_start(&task1_timer, ktime_set(0, 900000000), HRTIMER_MODE_REL); // 0.9s
} else {
i = 0;
}
return HRTIMER_NORESTART;
}
记录历经的路,分享个人总结与感悟。