Show me the money
分类: LINUX
2010-05-04 14:02:21
1. Linux时钟处理流程
2. 时钟源和时钟设备
clock source:时钟源,代表硬件计时器
clock event device:时钟事件设备。每个时钟中断触发一个clock event,通过调用clock event绑定的event_handler,通知linux内核更新系统时间。
从逻辑上讲,时钟源和时钟事件设备是互不相关的。如果不注册时钟源,某些系统自带有默认的时钟源;比如MIPS,默认的时钟源是c0_count寄存器。
3. 如何实现正确的clocksource_read
clocksource_read是clock source的一个回调函数,系统通过这个回调函数获取硬件定时器的计数值。但是,如何正确的返回计数值,却没有想像的那么简单。
linux内核中对于clocksource_read返回值的处理:
cycle_now = clocksource_read(clock); cycle_delta =
(cycle_now - clock->cycle_last) & clock->mask; clock->cycle_last = cycle_now; nsec = cyc2ns(clock, cycle_delta); |
kernel直接将两次计数值相减的结果作为时间间隔的基本单位,这实际上隐含了一个条件:
“硬件计数器”的最大计数值必须是2n-1,这样即使在计数器溢出的情况下,仍然可以获得正确的结果。
如果硬件计数器不能满足上述条件,那么需要通过软件维护一个虚拟的2n-1位计数器,在clocksource_read函数中返回该虚拟计数器的值,这样才能保证kernel的计数精度。
具体的实现方法是统计自从系统启动以来已发生的计时器中断的次数,
clock_count = N * latch + hwclock_value
应该要注意,如果进入clocksource_read函数时,系统中断已经被关闭,导致N不能被更新,在计算clock_count的时候应该将N加上1。
而且还有一个限制条件:系统中断关闭的时间不能超过两个tick,否则系统时间将会产生误差。(笔者在调试某款芯片的时候发现:当硬件计时器计数减为零的时候,计时器的中断pending位并没有被置上;导致两次clocksource_read返回值之差为负数,从而导致settimeofday函数无法设置正确的时间!!就这个一个小小的问题,困扰了笔者几乎一星期之久。)