linux不靠譜的sleep

來源:互聯網
上載者:User

首先感謝如下兩篇的blog,讓我走出了很大的一個誤區:


http://www.cppblog.com/kongque/archive/2011/01/18/138765.aspx

http://blog.csdn.net/zjwoody/article/details/7882240


在我的一個項目中,因為需要與串口通訊,每次讀寫都需要延時usleep(1000)=1ms,但是通訊量非常大,每一次工作這樣的通訊大概有300次左右,這樣算下耗時應該是300ms左右。


但是通過strace列印出系統函數調用發現實際接近900ms,仔細觀察strace日誌才發現,每次usleep(1000000)其實都延時了2ms,之後上網搜尋才發現usleep是不精確的。


1.sleep的精度是秒2.usleep的精度是微妙,不精確3.select的精度是微妙,精確    struct timeval delay;    delay.tv_sec = 0;    delay.tv_usec = 20 * 1000; // 20 ms    select(0, NULL, NULL, NULL, &delay);4.nanosleep的精度是納秒,不精確unix、linux系統盡量不要使用usleep和sleep而應該使用nanosleep,使用nanosleep應注意判斷傳回值和錯誤碼,否則容易造成cpu佔用率100%。

這是第一篇blog中提到的,然後第二篇blog中提供的測試代碼,本人做了少量改動(原作者沒有列印出usleep(0)時的資訊),代碼如下:

/*        make:  gcc -o test_sleep test_sleep.c */#include <stdio.h>#include <stdlib.h>#include <time.h>#include <sys/time.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#define PRINT_USEAGE  { \   fprintf(stderr,"\n Usage: %s usec ",argv[0]); \   fprintf(stderr,"\n\n");\  }int main (int argc, char **argv){  unsigned int nTimeTestSec = 0;        /* sec */  unsigned int nTimeTest = 0;        /* usec */  struct timeval tvBegin;  struct timeval tvNow;  int ret = 0;  unsigned int nDelay = 0;        /* usec */  fd_set rfds;  struct timeval tv;  int fd = 1;  int i = 0;  struct timespec req;  unsigned int delay[20] =    { 500000, 100000, 50000, 10000, 1000, 900, 500, 100, 10, 1, 0 };  int nReduce = 0;                /* 誤差  */#if 0  if (argc < 2)    {      PRINT_USEAGE;      exit (1);    }  nDelay = atoi (argv[1]);#endif  fprintf (stderr, "%18s%12s%12s%12s\n", "function", "time(usec)", "realTime",           "reduce");  fprintf (stderr,           "-------------------------------------------------------------------\n");  for (i = 0; i < 11; i++)    {      if (delay[i] < 0)        break;      nDelay = delay[i];      /*      test usleep */      gettimeofday (&tvBegin, NULL);      ret = usleep (nDelay);      if (-1 == ret)        {          fprintf (stderr, " usleep error . errno=%d [%s]\n", errno,                   strerror (errno));        }      gettimeofday (&tvNow, NULL);      nTimeTest =        (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -        tvBegin.tv_usec;      nReduce = nTimeTest - nDelay;      fprintf (stderr, "/t usleep       %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);      /*      test nanosleep */      gettimeofday (&tvBegin, NULL);      req.tv_sec = nDelay / 1000000;      req.tv_nsec = (nDelay % 1000000) * 1000;      ret = nanosleep (&req, NULL);      if (-1 == ret)        {          fprintf (stderr, "/t nanosleep    %8u   not support\n", nDelay);        }      else        {          gettimeofday (&tvNow, NULL);          nTimeTest =            (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -            tvBegin.tv_usec;          nReduce = nTimeTest - nDelay;          fprintf (stderr, "/t nanosleep    %8u   %8u   %8d\n", nDelay,                   nTimeTest, nReduce);        }      /*      test select */      gettimeofday (&tvBegin, NULL);      FD_ZERO (&rfds);      FD_SET (fd, &rfds);      tv.tv_sec = 0;      tv.tv_usec = nDelay;      ret = select (0, NULL, NULL, NULL, &tv);      if (-1 == ret)        {          fprintf (stderr, " select error . errno=%d [%s]\n", errno,                   strerror (errno));        }      gettimeofday (&tvNow, NULL);      nTimeTest =        (tvNow.tv_sec - tvBegin.tv_sec) * 1000000 + tvNow.tv_usec -        tvBegin.tv_usec;      nReduce = nTimeTest - nDelay;      fprintf (stderr, "/t select       %8u   %8u   %8d\n", nDelay, nTimeTest,               nReduce);    }  return 0;}

程式顯示如下:

[root@localhost test]# ./sleep_com           function  time(usec)    realTime      reduce-------------------------------------------------------------------/t usleep         500000     501575       1575/t nanosleep      500000     501861       1861/t select         500000     499893       -107/t usleep         100000     101933       1933/t nanosleep      100000     101957       1957/t select         100000      99946        -54/t usleep          50000      51954       1954/t nanosleep       50000      51962       1962/t select          50000      49991         -9/t usleep          10000      11941       1941/t nanosleep       10000      11973       1973/t select          10000       9974        -26/t usleep           1000       2976       1976/t nanosleep        1000       2974       1974/t select           1000        993         -7/t usleep            900       1968       1068/t nanosleep         900       1978       1078/t select            900        966         66/t usleep            500       1971       1471/t nanosleep         500       1973       1473/t select            500        992        492/t usleep            100       1970       1870/t nanosleep         100       1979       1879/t select            100        968        868/t usleep             10       1972       1962/t nanosleep          10       1974       1964/t select             10        993        983/t usleep              1       1969       1968/t nanosleep           1       1983       1982/t select              1        960        959/t usleep              0        988        988/t nanosleep           0        961        961/t select              0          5          5/t usleep              0        971        971

通過上表可以看出usleep(1000)實際 延時將近3ms。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.