内核提供的定时器分辨率是受jiffies来定时的,所以会受到HZ影响,如果HZ是100,代表每秒钟产生100次中断,那一个jiffies就需要10毫秒,所以精度为10毫秒,但实测过的同学定时器秒级或者毫秒级都会有点误差,如果精度需要精准或者需要微秒甚至是纳秒级别,就要用到高分辨率定时器hrtimer。
高分辨率定时器要的数据结构struct hrtimer
Linux内核使用 hrtimer 结构体表示内核定时器, hrtimer 定义在文件include/linux/hrtimer.h 中
struct hrtimer {
struct timerqueue_node node; // 用于链表管理的节点
ktime_t _softexpires;// 到期时间
enum hrtimer_restart (*function)(struct hrtimer *);// 定时到期时的回调函数
struct hrtimer_clock_base *base; //指向定时器基的指针(每个CPU和每个时钟)
u8 state; // 状态标志
u8 is_rel;//设置定时器是否相对
u8 is_soft;//在软中断上下文中设置hrtimer是否过期
u8 is_hard;//在硬中断上下文中设置hrtimer是否过期
ANDROID_KABI_RESERVE(1);
};
枚举高精度模式定时器的到期模式
enum hrtimer_mode {
HRTIMER_MODE_ABS = 0x00,
HRTIMER_MODE_REL = 0x01,
HRTIMER_MODE_PINNED = 0x02,
HRTIMER_MODE_SOFT = 0x04,
HRTIMER_MODE_HARD = 0x08,
HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED,
HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED,
HRTIMER_MODE_ABS_SOFT = HRTIMER_MODE_ABS | HRTIMER_MODE_SOFT,
HRTIMER_MODE_REL_SOFT = HRTIMER_MODE_REL | HRTIMER_MODE_SOFT,
HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT,
HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT,
HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD,
HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD,
HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD,
HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD,
};
分为五种高精度模式:
-
绝对模式
-
相对模式
-
计时器绑定到CPU(仅在启动计时器时考虑)
-
软中断到期模式(HRTIMER_MODE_SOFT)
-
硬中断到期模式(HRTIMER_MODE_HARD)
软中断到期模式的高精度定时器,到期的时候在类型为 HRTIMER_SOFTIRQ 的软中断里面执行定时器回调函数。在实时内核中,软中断由软中断线程执行,或者在进程开启软中断的时候执行。
硬中断到期模式的高精度定时器,到期的时候在时钟中断处理程序里面执行定时器回调函数。如果没有指定到期模式,那么在实时内核中默认使用软中断到期模式。
hrtimer_init 是 Linux 内核中用于初始化高分辨率定时器的函数
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id , enum hrtimer_mode mode)
hrtimer_start 是 Linux 内核中用于启动高分辨率定时器的函数
int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
hrtimer_forward_now 是 Linux 内核中用于调整高分辨率定时器(high-resolution timer,hrtimer)到期时间的一个函数
void hrtimer_forward_now(struct hrtimer *timer,ktime_t interval)
hrtimer_cancel 是 Linux 内核中用于取消高分辨率定时器的函数
hrtimer_cancel(struct hrtimer *timer)
ktime_set 用于设置一个定时器的到期时间
ktime_t t = ktime_set(secs, nsecs);
高分辨率定时器使用包括单次使用和循环使用
单次定时1s
#include
#include
#include
#include
#include
staticstruct hrtimer my_timer;
staticint count = 0;
enum hrtimer_restart my_timer_callback(struct hrtimer *timer)
{
pr_info(KERN_INFO "High-resolution timer expired after 1 second\n");
return HRTIMER_NORESTART; // 不重复定时器
}
static int __init my_module_init(void)
{
ktime_t ktime;
pr_info("High-Resolution Timer Example Module Loaded\n");
// 设置定时器初始时间为 1 秒
ktime = ktime_set(1, 0); // 1 秒, 0 纳秒
hrtimer_init(&my_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
my_timer.function = my_timer_callback;
hrtimer_start(&my_timer, ktime, HRTIMER_MODE_REL);
return0;
}
static void __exit my_module_exit(void)
{
// 停止定时器
hrtimer_cancel(&my_timer);
pr_info("High-Resolution Timer Example Module Unloaded\n");
}
module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("High-Resolution Timer Example");
MODULE_AUTHOR("Pan Shuai");
循环定时1s的例子
#include
#include
#include
#include
#include
staticstruct hrtimer my_timer;
staticint count = 0;
enum hrtimer_restart my_timer_callback(struct hrtimer *timer)
{
count++;
pr_info("Timer expired! Count: %d\n", count);
// 重新启动定时器,设置下次到期时间为 1 秒
hrtimer_forward_now(timer, ms_to_ktime(1000));
return HRTIMER_RESTART; // 重复定时器
}
static int __init my_module_init(void)
{
ktime_t ktime;
pr_info("High-Resolution Timer Example Module Loaded\n");
// 设置定时器初始时间为 1 秒
ktime = ktime_set(1, 0); // 1 秒, 0 纳秒
hrtimer_init(&my_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
my_timer.function = my_timer_callback;
hrtimer_start(&my_timer, ktime, HRTIMER_MODE_REL);
return0;
}
static void __exit my_module_exit(void)
{
// 停止定时器
hrtimer_cancel(&my_timer);
pr_info("High-Resolution Timer Example Module Unloaded\n");
}
module_init(my_module_init);
module_exit(my_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("High-Resolution Timer Example");
MODULE_AUTHOR("Pan Shuai");