现在的位置: 首页 > 综合 > 正文

短延迟 usleep , msleep, nanosleep select

2013年01月20日 ⁄ 综合 ⁄ 共 4020字 ⁄ 字号 评论关闭

关于短延迟 sleep usleep nanosleep select

udelay(unsigned long usecs);
mdelay(unsigned long msecs);

前者用软件循环指定的微妙数,后者调用前者达到延迟毫秒级。udelay
函数只能用于获取较短的时间延迟,因为loops_per_second值的精度只有8位,所以,当计算更长的延迟时会积累出相当大的误差。尽管最大能允
许的延迟将近1秒(因为更长的延迟就要溢出),推荐的 udelay 函数的参数的最大值是取1000微秒(1毫秒)。延迟大于 11
毫秒时可以使用函数 mdelay。

要特别注意的是 udelay 是个忙等待函数(所以 mdelay 也是),在延迟的时间段内无法运行其他的任务,因此要十分小心,尤其是 mdelay,除非别无他法,要尽量避免使用。
mdelay 在 Linux 2.0 中并不存在,头文件 sysdep.h 弥补了这一缺陷。

关于 usleep sleep 主要的差距在精确程度上,不过网友有关于这个方面的精辟论断:
同样我觉得
select也是比较好的定时机制,不过大家可以看igmp-proxy的源代码。主函数里面用setitimer和select同时定时是一个相当好的想法。

#################################################################
再论精确延时(usleep,nanosleep,select)

/*
        make: gcc -o test_sleep test_sleep.c
*/
/*        #include "comm_main.h" */
#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 < 20; 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;
}

---------------------------------------------------------------------------------------------------------------------------------------------------

测试
IBM AIX 3.4 单CPU
        sleep 可以在多线程中使用,只阻塞本线程,不影响所属进程中的其它线程
        不支持 nanosleep
        支持 usleep 和 select
        以下采用 gettimeofday 对 usleep 和 select 的实际精确情况进行测试分析
          function time(usec)    realTime      reduce
-------------------------------------------------------------------
         usleep         500000     500026         26
         nanosleep      500000   not support
         select         500000     500026         26
         usleep         100000     100021         21
         nanosleep      100000   not support
         select         100000     100025         25
         usleep          50000      50021         21
         nanosleep       50000   not support
         select          50000      50107        107

抱歉!评论已关闭.