Linux内核中的高精度定时器:hrtimer机制详解
作为一名深耕操作系统和嵌入式开发的工程师,我对Linux内核中的高精度定时器(hrtimer)机制有着深入的理解。hrtimer提供了微秒甚至纳秒级的定时精度,是实时应用的关键基础设施。
传统定时器的局限
传统的基于jiffies的定时器存在以下局限:
- 精度受限:受HZ值限制,通常只有1-10ms精度
- 粒度粗糙:无法满足实时应用的需求
- 累积误差:长时间运行会产生较大误差
hrtimer的核心特性
hrtimer提供了以下特性:
- 高精度:支持微秒甚至纳秒级精度
- 多种时钟源:支持多种时钟基准
- 红黑树管理:高效地管理大量定时器
- 软中断处理:在软中断上下文中执行
hrtimer的核心API
1. 初始化和设置
// 定义hrtimer
struct hrtimer my_timer;
// 初始化
hrtimer_init(&my_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
my_timer.function = my_timer_callback;
// 时钟类型
// CLOCK_REALTIME: 系统实时时钟(受NTP调整影响)
// CLOCK_MONOTONIC: 单调时钟(不受NTP影响)
// CLOCK_BOOTTIME: 包含挂起时间的单调时钟
// 模式
// HRTIMER_MODE_ABS: 绝对时间
// HRTIMER_MODE_REL: 相对时间
// HRTIMER_MODE_PINNED: 绑定到特定CPU
2. 启动和取消
// 启动定时器(相对时间)
hrtimer_start(&my_timer, ms_to_ktime(100), HRTIMER_MODE_REL);
// 启动定时器(绝对时间)
hrtimer_start(&my_timer, ktime_set(5, 0), HRTIMER_MODE_ABS);
// 取消定时器
hrtimer_cancel(&my_timer);
// 尝试取消(如果正在执行则等待)
int ret = hrtimer_try_to_cancel(&my_timer);
if (ret == 1)
// 成功取消
else if (ret == 0)
// 定时器正在执行
// 重启定时器
hrtimer_restart(&my_timer);
3. 回调函数
enum hrtimer_restart my_timer_callback(struct hrtimer *timer)
{
// 执行定时任务
do_timer_work();
// 如果需要周期性执行,重新设置定时器
hrtimer_forward_now(timer, ms_to_ktime(100));
return HRTIMER_RESTART; // 重启定时器
// return HRTIMER_NORESTART; // 不重启
}
hrtimer的实现原理
1. 数据结构
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;
u8 is_soft;
u8 is_hard;
};
struct hrtimer_clock_base {
struct timerqueue_head head;
ktime_t resolution;
ktime_t (*get_time)(void);
ktime_t softirq_time;
ktime_t offset;
};
2. 红黑树管理
hrtimer使用红黑树管理定时器队列:
- 高效查找:O(log n)时间复杂度
- 快速插入:O(log n)时间复杂度
- 顺序遍历:按到期时间排序
3. 时钟事件设备
hrtimer依赖时钟事件设备(clockevents):
struct clock_event_device {
const char *name;
u64 mult;
u32 shift;
int rating;
int irq;
void (*set_next_event)(unsigned long evt, struct clock_event_device *);
void (*set_state_shutdown)(struct clock_event_device *);
void (*set_state_periodic)(struct clock_event_device *);
void (*set_state_oneshot)(struct clock_event_device *);
void (*tick_resume)(struct clock_event_device *);
};
使用场景
1. 实时任务调度
struct hrtimer rt_timer;
void setup_rt_timer(void)
{
hrtimer_init(&rt_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
rt_timer.function = rt_task_callback;
// 设置1ms周期
hrtimer_start(&rt_timer, ms_to_ktime(1), HRTIMER_MODE_REL);
}
enum hrtimer_restart rt_task_callback(struct hrtimer *timer)
{
// 执行实时任务
execute_rt_task();
// 重新设置下一个周期
hrtimer_forward_now(timer, ms_to_ktime(1));
return HRTIMER_RESTART;
}
2. 多媒体同步
struct hrtimer video_timer;
ktime_t frame_interval;
void init_video_sync(int fps)
{
frame_interval = ktime_set(0, NSEC_PER_SEC / fps);
hrtimer_init(&video_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
video_timer.function = video_frame_callback;
}
enum hrtimer_restart video_frame_callback(struct hrtimer *timer)
{
// 显示下一帧
display_next_frame();
hrtimer_forward_now(timer, frame_interval);
return HRTIMER_RESTART;
}
3. 精确延时
void precise_delay_us(unsigned int us)
{
ktime_t start, end;
start = ktime_get();
end = ktime_add_us(start, us);
while (ktime_before(ktime_get(), end))
cpu_relax();
}
性能优化建议
1. 避免频繁启停
// 错误:频繁创建和销毁
void do_work(void)
{
struct hrtimer timer;
hrtimer_init(&timer, ...);
hrtimer_start(&timer, ...);
hrtimer_cancel(&timer);
}
// 正确:复用定时器
static struct hrtimer timer;
void init(void)
{
hrtimer_init(&timer, ...);
}
void do_work(void)
{
hrtimer_start(&timer, ...);
}
2. 使用合适的时钟源
// 对于不需要绝对时间的场景,使用MONOTONIC
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
// 对于需要跨挂起保持的场景,使用BOOTTIME
hrtimer_init(&timer, CLOCK_BOOTTIME, HRTIMER_MODE_REL);
3. 批量处理
// 将多个短定时器合并为一个长定时器
static struct hrtimer batch_timer;
static LIST_HEAD(pending_work);
enum hrtimer_restart batch_callback(struct hrtimer *timer)
{
struct work *work;
// 批量处理所有待处理的工作
list_for_each_entry(work, &pending_work, list) {
process_work(work);
}
// 根据下一个工作的时间重新设置定时器
ktime_t next_time = get_next_work_time();
hrtimer_set_expires(timer, next_time);
return HRTIMER_RESTART;
}
与传统定时器的对比
| 特性 | hrtimer | 传统timer |
|---|---|---|
| 精度 | 微秒/纳秒 | 毫秒 |
| 时钟源 | 多种选择 | 基于jiffies |
| 实现 | 红黑树 | 链表 |
| 开销 | 较高 | 较低 |
| 适用场景 | 实时应用 | 一般延时 |
调试和监控
# 查看hrtimer统计
cat /proc/timer_list
# 查看时钟事件设备
cat /proc/timer_list | grep "Clock Event Device"
# 查看当前定时器
cat /proc/timer_list | grep "hrtimer"
总结
hrtimer是Linux内核中实现高精度定时的关键机制,它为实时应用、多媒体同步等场景提供了必要的支持。作为嵌入式开发者,理解hrtimer的工作原理和使用方法,对于开发实时系统至关重要。

1617

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



