首页 > 代码库 > linux内核中的时间接口

linux内核中的时间接口

    时钟中断:是硬件中的定时器以固定的时间产生一次中断。

    时钟中断频率:1s中的时钟中断次数;

    我们可以通过更改相应的配置,来改变一个系统的时钟中断频率。

   先来看看X86平台上的时钟中断频率:

   wKiom1R1l5uhv2gcAACy4yLfvz0778.jpg

   wKioL1R1mM6TApGJAAE8DP2bx7g676.jpg


   有以上可知,内核通过使用 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变量中的时
钟中断数转换为时间的。

本文出自 “阿辉仔” 博客,请务必保留此出处http://weiguozhihui.blog.51cto.com/3060615/1582974

linux内核中的时间接口