低精度定時器基於時間輪算法,與jiffies關係緊密,精度爲ms級,應用場景一般爲“超時”退出。
因此,對於精度要求較高的驅動或應用場景,內核重新設計了一套軟件架構,它可以提供納秒級的定時精度,基於紅黑樹實現。
hrtimer的結構
與普通timer類似,每一個CPU也維護一個hrtimer的結構hrtimer_cpu_base,
struct hrtimer_cpu_base {
raw_spinlock_t lock;
seqcount_t seq;
struct hrtimer *running;
unsigned int cpu;
unsigned int active_bases;
unsigned int clock_was_set_seq;
bool migration_enabled;
bool nohz_active;
#ifdef CONFIG_HIGH_RES_TIMERS //高精度配置
unsigned int in_hrtirq : 1,
hres_active : 1,
hang_detected : 1;
ktime_t expires_next; //定時器的到期時間
struct hrtimer *next_timer;
unsigned int nr_events;
unsigned int nr_retries;
unsigned int nr_hangs;
unsigned int max_hang_time;
#endif
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; //時鐘源
} ____cacheline_aligned;
其中hrtimer的結構,
struct hrtimer {
struct timerqueue_node node;
ktime_t _softexpires; //到期時間
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base; //時鐘源
u8 state; //hrtimer當前狀態
u8 is_rel;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
};
hrimer的有以下幾種狀態,
enum hrtimer_base_type {
HRTIMER_BASE_MONOTONIC, // 單調遞增的monotonic時間,不包含休眠時間
HRTIMER_BASE_REALTIME, // 平常使用的牆上真實時間
HRTIMER_BASE_BOOTTIME, // 單調遞增的boottime,包含休眠時間
HRTIMER_MAX_CLOCK_BASES, // 用於後續數組的定義
};
hrtimer的使用
初始化hrtimer:
void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
enum hrtimer_mode mode);
激活hrtimer:
int hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode);
hrtimer_start函數將一個hrtimer加入到一個按照到期時間排序的紅黑樹中
如果需要指定到期範圍,則可以使用hrtimer_start_range_ns
hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
unsigned long range_ns, const enum hrtimer_mode mode);
取消hrtimer:
int hrtimer_cancel(struct hrtimer *timer);
推遲hrtimer的到期時間:
extern u64
hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
/* Forward a hrtimer so it expires after the hrtimer's current now */
static inline u64 hrtimer_forward_now(struct hrtimer *timer,
ktime_t interval)
{
return hrtimer_forward(timer, timer->base->get_time(), interval);
}
使用示例
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/jiffies.h>
static struct hrtimer timer;
ktime_t kt;
static enum hrtimer_restart hrtimer_handler(struct hrtimer *timer)
{
//kt = ktime_set(1, 10);
printk("hrtimer start\n");
hrtimer_forward(timer, timer->base->get_time(), kt);
return HRTIMER_RESTART;
}
static int __init test_init(void)
{
pr_info("timer resolution: %lu\n", TICK_NSEC);
kt = ktime_set(1, 10); /* 1 sec, 10 nsec */
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
//hrtimer_set_expires(&timer, kt);
hrtimer_start(&timer, kt, HRTIMER_MODE_REL);
timer.function = hrtimer_handler;
printk("test init\n");
return 0;
}
static void __exit test_exit(void)
{
hrtimer_cancel(&timer);
printk(" test exit\n");
return;
}
MODULE_LICENSE("GPL");
module_init(test_init);
module_exit(test_exit);
更多hrtimer的知識參考博文:
http://blog.csdn.net/droidphone/article/details/8074892