处理时间委托包括如下任务,按复杂度依次上升:
- 测量时间流失和比较时间
- 知道当前时间
- 指定时间量的延时操作
- 调度异步函数在之后的时间发生
一、测量时间流失
系统定时硬件规律的产生定时器中断,在内核启动阶段,根据Hz的值,设置这个间隔时间。
HZ的值各不相同,不同平台硬件的参数也不一样,即便你知道HZ的值,在编程时也不应该依赖它。
1.1 使用jiffies计数器
- 计数器头文件位于<linux/jiffies.h>,但是你更经常使用<linux/sched.h>
- jiffies和jiffies_64必须是当作只读的
有时代码需要计算一个将来的时间戳,这个代码不用考虑溢出问题:
#include <linux/jiffies.h> unsigned long j, stamp_1, stamp_half, stamp_n; j = jiffies; /* read the current value */ stamp_1 = j + HZ; /* 1 second in the future */ stamp_half = j + HZ/2; /* half a second */ stamp_n = j + n * HZ / 1000; /* n milliseconds */
有了上面的时间戳,下面是比较函数:
#include <linux/jiffies.h> int time_after(unsigned long a, unsigned long b); int time_before(unisgned long a, unsigned long b); int time_after_eq(unsigned long a, unsigned long b); int time_before_eq(unsigned long a, unsigned long b);
上面的函数其实可以替换为:
diff = (long)t2 - (long)t1;
然后通过转换一个jiffies差为毫秒:
msec = diff * 1000 / HZ
- 有时内核需要和用户空间交换时间表示,用户空间使用的是struct timeval和struct timespec来表示时间。
#include <linux/time.h> unsigned long timespec_to_jiffies(struct timespec *value); void jiffies_to_timespec(unsigned long jiffies, struct timespec *value); unsigned long timeval_to_jiffies(struct timeval *value); void jiffies_to_timeval(unsigned long jiffies, struct timeval *value);
在32位系统中,读取64位jiffies有同步的问题,所以内核直接给了函数:
#include <linux/jiffies.h> u64 get_jiffies_64(void);
1.2 处理器特定的寄存器
如果你要测量时间间隔非常短,或者精度要求非常高,那么放弃移植性