时钟中断:是硬件中的定时器以固定的时间产生一次中断。
时钟中断频率: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
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变量中的时
钟中断数转换为时间的。