时钟中断:是硬件中的定时器以固定的时间产生一次中断。
时钟中断频率:1s中的时钟中断次数;
我们可以通过更改相应的配置,来改变一个系统的时钟中断频率。
先来看看X86平台上的时钟中断频率:
有以上可知,内核通过使用 HZ 宏来表示在内核中的时钟频率为CONFIG_HZ,当然我们就可以通过改变
相应的体系结构中的config文件中CONFIG_HZ的值,来调整内核中的时钟频率值。
如果 CONFIG_HZ=1000的话,内核通过时钟频率所能测出的时间的分辨率为 1ms。
linux系统中,通过使用 unsigned long jiffies变量或 unsigned long long jiffies_64变量来统计系统自开机以来到当前的时钟中断数。
由于jiffies、 jiffies_64是系统中的全局变量,所以一般不要直接使用jiffies、jiffies_64变量。可以通过如下的方法使用:
unsigned long stamp_1, stamp_2, stamp_3,stamp_4; stamp_1 = jiffies; stamp_2 = stamp_1 + HZ; // 未来的1s, stamp_3 = stamp_1 + HZ / 2; // 未来的0.5s; stamp_4 = stamp_1 + n * HZ /1000; // 未来的1ms;
通过使用如下函数来判断两个变量中的时钟频率值得大小:
int time_after(unsigned long a, unsigned long b) 如果 a > b ,返回 1, 否则返回 0; int time_before(unsigned long a, unsigned long b) 如果 a < b 返回 1, 否则返回0; int time_after_eq(unsigned long a, unsigned long b) 如果 a >= b 返回 1, 否则返回0; int time_before_eq(unsigned long a, unsigned long b) 如果 a <= b 返回 1, 否则返回0;
在内核中是通过时钟中断来管理时间的,即通过jiffies、jiffies_64这两个变量中的值来管理时间的。
在32位的体系结构体中,jiffies_64这个变量是有两个32位的变量组合而成的。如果直接访问jiffies_64变量肯定不会是原子访问,这就造成了有可能数据不同步的问题。所以要访问jiffies_64的话,最好使用下面这个函数,在32处理器上:
u64 get_jiffies_64(void); 使用方法: u64 time; time = get_jiffies_64();
而在用户空间中,用来表示时间的结构体为:
struct timeval { __kernel_time_t tv_sec ; // seconds __kernel_suseconds_t tv_usec; //microseconds } struct timespec { __kernel_time_t tv_sec ; // seconds long tv_nsec ; // nanoseconds; }
这两个结构体的区别是:timeval的时间分辨率是:毫秒;
timespec的时间分辨率是:纳秒;
如果想要更精确的时间度的话,使用timespec;
现在知道,内核与用户空间对时间的表示方法是不同的,那么如果内核时间与用户空间时间进行相互转换;内核中提供了以下几个接口来实现:
unsigned long timespec_to_jiffies( struct timespec *value ); 用于将用户空间时间转换称为内核中的时钟中断数,并将其作为函数的返回值返回。 void jiffies_to_timespec( unsigned long jiffies, struct timespec *value ); 将jiffies或jiffies_64中的时钟中断数,转化为用户空间中的时间值,存入value之中; unsigend long timeval_to_jiffies( struct timeval *value ); void jiffies_to_timeval( unsigned long jiffies, struct timeval *vlaue );
我们如何通过年、月、日、小时、分钟、秒等这些信息,将其转换为内核中的jiffies值。
内核也给我们提供了一个接口:
unsigned long mktime( unsigned int year, unsigned int mon, unsigned int day, unsigned int hour, unsigned int min, unsigned int sec); 这个函数的返回值为时钟中断数;
直接获取内核中的时间,并将其转换为struct timeval, struct timespec等时间形式;
void do_gettimeofday(struct timeval *value); 获取内核中的时间,并将其转换为struct timeval存放在value之中; 当然通过do_gettimeofday()获取的时间的分辨率为1ms; struct timespec current_kernel_time(void); 获取内核中的时间,并将其转换为struct timespec时间格式; do_gettimeofday(), current_kernel_time()这两个函数都是通过将内核中的jiffies变量中的时 钟中断数转换为时间的。