linux下的time处理

本文详细解析Linux内核中三种时间概念:Walltime、Processtime和Monotonictime,介绍它们的区别与表示方式。进一步讨论了如何通过Java代码表示时间,包括时间值的精确度和表示结构,如`timeval`、`timespec`等。此外,文章还阐述了获取不同时间精度的方法,如`clock_getres`函数,并提供了实例代码展示如何获取各种时钟的精度。最后,文章对比了设置时间的函数,并强调了在大多数系统中只能设置CLOCK_REALTIME时钟。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 在内核中有3个不同的时间:

Wall time(real time), Process time和Monotonic time.

Wall time,也就是rtc时钟。

Process time,进程执行的时间。

Monotonic time,也就是系统从boot后到当前的时间。

表示时间的数据结构:

Java代码 复制代码  收藏代码
  1. typedef __timer_t timer_t;   
  2.   
  3. struct timeval   
  4.    {   
  5.     __time_t tv_sec;            /* Seconds.  */  
  6.       __suseconds_t tv_usec;      /* Microseconds.  */  
  7.    };   
  8.   
  9.  struct timespec   
  10. {   
  11.   __time_t tv_sec;            /* Seconds.  */  
  12.   long int tv_nsec;           /* Nanoseconds.  */  
  13.  };  
typedef __timer_t timer_t;

struct timeval
   {
    __time_t tv_sec;            /* Seconds.  */
      __suseconds_t tv_usec;      /* Microseconds.  */
   };

 struct timespec
{
  __time_t tv_sec;            /* Seconds.  */
  long int tv_nsec;           /* Nanoseconds.  */
 };


其中第三个最好,因为他能精确到纳秒。

上面的所能表示的是秒,我们有时需要更直观的表示,因此就有下面的数据结构;
Java代码 复制代码  收藏代码
  1. struct tm   
  2.  {   
  3.  int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */  
  4.    int tm_min;                   /* Minutes.     [0-59] */  
  5. int tm_hour;                  /* Hours.       [0-23] */  
  6.   int tm_mday;                  /* Day.         [1-31] */  
  7.  int tm_mon;                   /* Month.       [0-11] */  
  8.   int tm_year;                  /* Year - 1900.  */  
  9.   int tm_wday;                  /* Day of week. [0-6] */  
  10.  int tm_yday;                  /* Days in year.[0-365] */  
  11.   int tm_isdst;                 /* DST.         [-1/0/1]*/  
  12.   
  13.  #ifdef  __USE_BSD   
  14.   long int tm_gmtoff;           /* Seconds east of UTC.  */  
  15.    __const char *tm_zone;        /* Timezone abbreviation.  */  
  16.  #else  
  17.   long int __tm_gmtoff;         /* Seconds east of UTC.  */  
  18.    __const char *__tm_zone;      /* Timezone abbreviation.  */  
  19.  #endif   
  20.  };  
struct tm
 {
 int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
   int tm_min;                   /* Minutes.     [0-59] */
int tm_hour;                  /* Hours.       [0-23] */
  int tm_mday;                  /* Day.         [1-31] */
 int tm_mon;                   /* Month.       [0-11] */
  int tm_year;                  /* Year - 1900.  */
  int tm_wday;                  /* Day of week. [0-6] */
 int tm_yday;                  /* Days in year.[0-365] */
  int tm_isdst;                 /* DST.         [-1/0/1]*/

 #ifdef  __USE_BSD
  long int tm_gmtoff;           /* Seconds east of UTC.  */
   __const char *tm_zone;        /* Timezone abbreviation.  */
 #else
  long int __tm_gmtoff;         /* Seconds east of UTC.  */
   __const char *__tm_zone;      /* Timezone abbreviation.  */
 #endif
 };



clock_getres这个函数得到不同时钟的精度,也就是时钟间隔:

Java代码 复制代码  收藏代码
  1. int clock_getres(clockid_t clk_id, struct timespec *res);  
int clock_getres(clockid_t clk_id, struct timespec *res);


Java代码 复制代码  收藏代码
  1.  #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main()   
  5. {   
  6.     clockid_t clocks[]= {   
  7.          CLOCK_REALTIME,   
  8.         CLOCK_MONOTONIC,   
  9.          CLOCK_PROCESS_CPUTIME_ID,   
  10.          CLOCK_THREAD_CPUTIME_ID,   
  11.         (clockid_t) -1,   
  12.      };   
  13.     
  14.      int i;   
  15.      for(i=0;clocks[i] != (clockid_t) -1;i++)   
  16.     {   
  17.         struct timespec res;   
  18.         int ret;   
  19.         ret = clock_getres(clocks[i],&res);   
  20.         if(ret)   
  21.             perror("clock_getres");   
  22.         else  
  23.             printf("clock = [%d],sec = [%ld],nsec = [%ld]\n",clocks[i],res.tv_sec,res.tv_nsec);   
  24.     }   
  25.     return 1;   
  26. }  
  #include <stdio.h>
 #include <time.h>
 
 int main()
 {
     clockid_t clocks[]= {
          CLOCK_REALTIME,
         CLOCK_MONOTONIC,
          CLOCK_PROCESS_CPUTIME_ID,
          CLOCK_THREAD_CPUTIME_ID,
         (clockid_t) -1,
      };
  
      int i;
      for(i=0;clocks[i] != (clockid_t) -1;i++)
     {
         struct timespec res;
         int ret;
         ret = clock_getres(clocks[i],&res);
         if(ret)
             perror("clock_getres");
         else
             printf("clock = [%d],sec = [%ld],nsec = [%ld]\n",clocks[i],res.tv_sec,res.tv_nsec);
     }
     return 1;
 }


我的amd的cpu下,输出结果是这样的:

Java代码 复制代码  收藏代码
  1. clock = [0],sec = [0],nsec = [4000250]   
  2. clock = [1],sec = [0],nsec = [4000250]   
  3. clock = [2],sec = [0],nsec = [1]   
  4. clock = [3],sec = [0],nsec = [1]  
clock = [0],sec = [0],nsec = [4000250]
clock = [1],sec = [0],nsec = [4000250]
clock = [2],sec = [0],nsec = [1]
clock = [3],sec = [0],nsec = [1]


其中4000250刚好是0.04秒,也就是说x86的架构的系统时钟频率为250hz。。


得到当前的时间的函数:

Java代码 复制代码  收藏代码
  1. extern time_t time (time_t *__timer) __THROW;   
  2.   
  3. int gettimeofday(struct timeval *tv, struct timezone *tz);   
  4.   
  5. int clock_gettime(clockid_t clk_id, struct timespec *tp);  
extern time_t time (time_t *__timer) __THROW;

int gettimeofday(struct timeval *tv, struct timezone *tz);

int clock_gettime(clockid_t clk_id, struct timespec *tp);



Java代码 复制代码  收藏代码
  1.  #include <stdio.h>   
  2. #include <time.h>   
  3.   
  4. int main()   
  5. {   
  6.     clockid_t clocks[]= {   
  7.          CLOCK_REALTIME,   
  8.         CLOCK_MONOTONIC,   
  9.          CLOCK_PROCESS_CPUTIME_ID,   
  10.          CLOCK_THREAD_CPUTIME_ID,   
  11.         (clockid_t) -1,   
  12.      };   
  13.     
  14.      int i;   
  15.      for(i=0;clocks[i] != (clockid_t) -1;i++)   
  16.     {   
  17.         struct timespec res;   
  18.         int ret;   
  19.         ret = clock_gettime(clocks[i],&res);   
  20.         if(ret)   
  21.             perror("clock_getres");   
  22.         else  
  23.             printf("clock = [%d],sec = [%ld],nsec = [%ld]\n",clocks[i],res.tv_sec,res.tv_nsec);   
  24.     }   
  25.     return 1;   
  26. }  
  #include <stdio.h>
 #include <time.h>
 
 int main()
 {
     clockid_t clocks[]= {
          CLOCK_REALTIME,
         CLOCK_MONOTONIC,
          CLOCK_PROCESS_CPUTIME_ID,
          CLOCK_THREAD_CPUTIME_ID,
         (clockid_t) -1,
      };
  
      int i;
      for(i=0;clocks[i] != (clockid_t) -1;i++)
     {
         struct timespec res;
         int ret;
         ret = clock_gettime(clocks[i],&res);
         if(ret)
             perror("clock_getres");
         else
             printf("clock = [%d],sec = [%ld],nsec = [%ld]\n",clocks[i],res.tv_sec,res.tv_nsec);
     }
     return 1;
 }


通过结果可以看出4个时钟的不同含义。比如CLOCK_REALTIME我们可以看到结果就是从1970年以来所经过的秒数。。


设置时间的函数和get差不多:

Java代码 复制代码  收藏代码
  1. int stime(time_t *t);   
  2.   
  3. int settimeofday(const struct timeval *tv, const struct timezone *tz);   
  4.   
  5. int clock_settime(clockid_t clk_id, const struct timespec *tp);  
int stime(time_t *t);

int settimeofday(const struct timeval *tv, const struct timezone *tz);

int clock_settime(clockid_t clk_id, const struct timespec *tp);


这里要注意,在大部分系统我们设置时钟,只能设置CLOCK_REALTIME。。

这里还有一个更高级的函数:

Java代码 复制代码  收藏代码
  1. #include <sys/timex.h>   
  2.   
  3.        int adjtimex(struct timex *buf);  
#include <sys/timex.h>

       int adjtimex(struct timex *buf);


这个函数用来同步内核的时钟。具体的用法可以去看man。。

sleep的4个函数:
Java代码 复制代码  收藏代码
  1.   
  2. sleep   
  3. usleep   
  4. int nanosleep(const struct timespec *req, struct timespec *rem);   
  5. long sys_clock_nanosleep (clockid_t which_clock, int flags, const struct timespec *rqtp, struct timespec *rmtp);  
sleep
usleep
int nanosleep(const struct timespec *req, struct timespec *rem);
long sys_clock_nanosleep (clockid_t which_clock, int flags, const struct timespec *rqtp, struct timespec *rmtp);


sleep和usleep区别不大,一个是秒,一个是毫秒而已。

nanosleep和他们的区别是它使用纳秒,并且他不是用信号来实现的,因此建议使用nanosleep,而不要使用sleep和usleep。

而最后一个函数我们可以选择所取的时钟。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值