首页 > 代码库 > linux 下高精度时间

linux 下高精度时间

今天在公司代码中看到了使用select函数的超时功能作定时器的用法,便整理了如下几个Linux下的微秒级别的定时器。在我的Ubutu10.10 双核环境中,编译通过。

[cpp] view plain copy
 
  1. /* 
  2.  * @FileName: test_sleep.c 
  3.  * @Author: wzj 
  4.  * @Brief:  
  5.  *    
  6.  *   
  7.  * @History:  
  8.  *  
  9.  * @Date: 2012年02月07日星期二22:20:00 
  10.  *  
  11.  */   
  12. #include<stdio.h>  
  13. #include<stdlib.h>  
  14. #include<time.h>  
  15. #include<sys/time.h>  
  16. #include<errno.h>  
  17. #include<string.h>  
  18. #include<unistd.h>  
  19. #include<sys/types.h>  
  20. #include<sys/select.h>  
  21.   
  22.   
  23. int main(int argc, char **argv)  
  24. {  
  25.     unsigned int nTimeTestSec = 0;  
  26.     unsigned int nTimeTest = 0;  
  27.     struct timeval tvBegin;  
  28.     struct timeval tvNow;  
  29.     int ret = 0;  
  30.     unsigned int nDelay = 0;  
  31.     struct timeval tv;  
  32.     int fd = 1;  
  33.     int i = 0;  
  34.     struct timespec req;  
  35.   
  36.     unsigned int delay[20] =   
  37.         {500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0};  
  38.     int nReduce = 0; //误差  
  39.   
  40.     fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");  
  41.     fprintf(stderr, "----------------------------------------------------\n");  
  42.     for (i = 0; i < 20; i++)  
  43.     {  
  44.         if (delay[i] <= 0)  
  45.             break;  
  46.         nDelay = delay[i];  
  47.         //test sleep  
  48.         gettimeofday(&tvBegin, NULL);  
  49.         ret = usleep(nDelay);  
  50.         if(ret == -1)  
  51.         {  
  52.             fprintf(stderr, "usleep error, errno=%d [%s]\n", errno, strerror(errno));  
  53.         }  
  54.         gettimeofday(&tvNow, NULL);  
  55.         nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
  56.         nReduce = nTimeTest - nDelay;  
  57.   
  58.          fprintf (stderr, "\t usleep       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  59.   
  60.          //test nanosleep  
  61.          req.tv_sec = nDelay/1000000;  
  62.          req.tv_nsec = (nDelay%1000000) * 1000;  
  63.   
  64.          gettimeofday(&tvBegin, NULL);  
  65.          ret = nanosleep(&req, NULL);  
  66.          if (-1 == ret)  
  67.          {  
  68.             fprintf (stderr, "\t nanousleep   %8u   not support\n", nDelay);  
  69.          }  
  70.          gettimeofday(&tvNow, NULL);  
  71.          nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
  72.          nReduce = nTimeTest - nDelay;  
  73.          fprintf (stderr, "\t nanosleep    %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  74.   
  75.          //test select  
  76.          tv.tv_sec = 0;  
  77.          tv.tv_usec = nDelay;  
  78.   
  79.          gettimeofday(&tvBegin, NULL);  
  80.          ret = select(0, NULL, NULL, NULL, &tv);  
  81.          if (-1 == ret)  
  82.          {  
  83.             fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));  
  84.          }  
  85.   
  86.          gettimeofday(&tvNow, NULL);  
  87.          nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
  88.          nReduce = nTimeTest - nDelay;  
  89.          fprintf (stderr, "\t select       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  90.   
  91.          //pselcet  
  92.          req.tv_sec = nDelay/1000000;  
  93.          req.tv_nsec = (nDelay%1000000) * 1000;  
  94.   
  95.          gettimeofday(&tvBegin, NULL);  
  96.          ret = pselect(0, NULL, NULL, NULL, &req, NULL);  
  97.          if (-1 == ret)  
  98.          {  
  99.             fprintf(stderr, "select error. errno = %d [%s]\n", errno, strerror(errno));  
  100.          }  
  101.   
  102.          gettimeofday(&tvNow, NULL);  
  103.          nTimeTest = (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec - tvBegin.tv_usec;  
  104.          nReduce = nTimeTest - nDelay;  
  105.          fprintf (stderr, "\t pselect      %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);  
  106.   
  107.          fprintf (stderr, "--------------------------------\n");  
  108.   
  109.     }  
  110.       
  111.     return 0;  
  112. }  

 

 

    老大建议我们在对精度要求较高的情况下使用select()作为定时器,最大的好处就是不会影响信号处理,线程安全,而且精度能得到保证。在这个实验中,当时间延时时间较长时,select和pselect表现较差,当时间小于1毫秒时,他们的精确度便提高了,表现与usleep、nanosleep不相上下,有时精度甚至超过后者

linux 下高精度时间