您的位置:首页 > 运维架构 > Linux

linux 内核笔记之时间管理(三) : 高精度timer

2017-04-26 23:24 1791 查看
低精度定时器基于时间轮算法,与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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息