打印

Linux驱动学习笔记之一——高精度定时器(2)

[复制链接]
3686|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dianzijiangren|  楼主 | 2012-5-15 13:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先是配置并初始化hrtimers的API。在开始的时候我们讲struct hrtimer的时候,提到要使用struct hrtimer要先初始化,函数声明代码如下:
void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,


enum hrtimer_mode mode)
//
给定时钟初始化定时器

{

debug_init(timer, clock_id, mode);


__hrtimer_init(timer, clock_id, mode);

}
以上函数实现了一个高精度定时器的初始化,下面是相关元素的解释:
/**

* hrtimer_init –
给定时钟初始化定时器


* @timer:
将要被初始化的定时器


* @clock_id:
将要被用到的时钟


* @mode:
定时器模式 abs/rel


*/

mode可以使用五个常数,如下:
enum hrtimer_mode {

HRTIMER_MODE_ABS = 0x0,
/*
时间是绝对的 */

HRTIMER_MODE_REL = 0x1,
/*
时间是相对的 */

HRTIMER_MODE_PINNED = 0x02,
/*
定时器被绑定到CPU */

HRTIMER_MODE_ABS_PINNED = 0x02,


HRTIMER_MODE_REL_PINNED = 0x03,

};
hrtimer_init()函数里面调用了__hrtimer_init()函数,下面是该函数的原型:
static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,enum hrtimer_mode mode)
{

struct hrtimer_cpu_base *cpu_base;


int base;


memsettimer, 0, sizeof(struct hrtimer));


cpu_base = &__raw_get_cpu_var(hrtimer_bases);


if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)


clock_id = CLOCK_MONOTONIC;


base = hrtimer_clockid_to_base(clock_id);


timer->base = &cpu_base->clock_base[base];


timerqueue_init(&timer->node);

#ifdef CONFIG_TIMER_STATS

timer->start_site = NULL;


timer->start_pid = -1;


memset(timer->start_comm, 0, TASK_COMM_LEN);

#endif
}
__hrtimer_init()函数调用了struct hrtimer_cpu_base结构体对CPU进行相关的初始化,并使用memset()函数,原型如下:
void *memset(void *s, int c, size_t n)
{

int i;


char *ss = s;


for (i = 0; i < n; i++)


ss = c;


return s;

}
这个函数清空了memory里面的东西,完成了初始化,memset(timer, 0, sizeof(struct hrtimer))。
在这里注意一下,还是前面说到的一个问题,我用的源代码是3.2.12的,而2.6.X的源代码里所提供的,其实只有两个常数。
二、相关的接口代码
定时器初始化之后,进行设定定时器的到期时间,并启动定时器,函数声明代码hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode),timer代表将要被添加的定时器,tim代表到期时间,mode代表定时器模式。如果启动成功,则返回0,否则返回1。
如果要取消一个设置好的定时器,可以使用int hrtimer_cancel(struct hrtimer *timer)int hrtimer_try_to_cancel(struct hrtimer *timer),这两个函数的区别是,后者提供了额外的返回值-1,如果定时器当前正在执行因而无法停止,则返回-1.在这种情况下,hrtimer_cancel会一直等处理程序执行完毕。另外,如果定时器处于未激活状态,两个函数的返回值都是0,如果处于激活状态(即状态为HRTIMER_STATE_INACTIVE或者HRTIMER_STATE_ENQUEUED),二者都返回1(读者务必注意,在2.6.X版本的源代码中,处于激活状态的两个常数是HRTIMER_STATE_PENDING或者HRTIMER_STATE_ENQUEUED,无非改了模样了,这个注意一下就好)。
如果要重启一个取消的定时器,可以使用static inline int hrtimer_restart(struct hrtimer *timer)
上面讲的几个函数应该是最基本的,也没什么大的讲头,下面的函数才是高精度定时器的精彩之处,也就四高精度定时器的到期机制和回调函数的运行方式,运用红黑树的方法既节省资源又提高效率。
在讲精彩之处之前,首先要跟读者说一下几个补充知识,其实前面我们也已经提到了,无非这里重复和补充一下:
Ø
高精度定时器按照时间在一棵红黑树上排序。

Ø
他们独立于周期时钟,采用纳秒时间戳而非jiffies的时间规格。

Ø
This patch introduces a new subsystem for high-resolution kernel timers.这句话里的patch这个单词有点意思,他是说高精度定时器作为一个补丁包被安装到系统里的,在2.6.16之前是没有这个概念的。

Ø
高精度定时器的框架在编译的时候是在内核里,但是如果没有配置高精度定时器,那么高精度定时器是按照普通的定时器来运行。

Ø
最后一点,高精度定时器是采用红黑树算法实现的,而普通的定时器是采用时间轮循算法实现的.

根据上面的几点,我们可以知道高精度定时器框架总是有一部分会编译到内核中去的,即使禁止了对高分辨率定时器的支持。在这种情况下,高分辨率定时器的到期是有一个低分辨率时钟驱动的。这避免了代码复制,因为高分辨率定时器的用户,在没有高分辨率计时能力的系统上,无需对时间相关代码提供一个额外的版本。这种情况下,仍然会采用高分辨率框架,但只是以低分辨率运行。即使高分辨率定时器支持已经编译到内核中,但在启动时只提供了低分辨率计时功能,这与上述情况是相同的。因此我们在这里讲的高分辨率定时器,要分成两种情况,一种是高分辨率模式下的高分辨率定时器,另一种是高分辨率模式下的低分辨率定时器。

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:终于,我也改行到互联网了

18

主题

558

帖子

3

粉丝