【Linux】延时函数sleep、usleep、nanosleep、select、pselect的比较

1、简介

sleep()-------以秒为单位
#include
unsigned int sleep(unsigned int seconds);
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余秒数。
在linux中,sleep是通过nanosleep实现的。在一些其他系统中(例如POSIX.1),它是通过alarm()来实现的。

usleep()----以微秒为单位
#include
unsigned int usleep(unsigned int useconds);
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余微秒数。

nanosleep( )---------以纳秒为单位
#include
struct timespec
{
time_t tv_sec; /* 秒seconds /
long tv_nsec; /
纳秒nanoseconds */
};
int nanosleep(const struct timespec req, struct timespec rem);
return: 若进程暂停到参数
req所指定的时间,成功则返回0,若有信号中断则返回-1,并且将剩余微秒数记录在
rem中。
req->tv_sec是以秒为单位,而tv_nsec以毫微秒为单位(10的-9次方秒)。
由于调用nanosleep是是进程进入TASK_INTERRUPTIBLE,这种状态是会相应信号而进入TASK_RUNNING状态的。

2、注意

使用这些函数时一定要注意判断返回值。有时候会出现sleep函数被系统中断的情况,导致结果不符合预期。
while (nanosleep(&ts, &ts) == -1 && errno == EINTR) {}

3、精确度对比

低精度情况(100000us及以上):usleep和nanosleep表现差不多。select和pselect表现较差。
高精度情况(100000us及以上):四者表现差不多。
fuction time(usec) realtime reduce

----------------------------------------------------
        usleep         500000     500091         91
        nanosleep      500000     500089         89
        select         500000     500540        540
        pselect        500000     500549        549
--------------------------------
        usleep         100000     100078         78
        nanosleep      100000     100110        110
        select         100000     100157        157
        pselect        100000     100149        149
--------------------------------
        usleep          50000      50091         91
        nanosleep       50000      50107        107
        select          50000      50111        111
        pselect         50000      50084         84
--------------------------------
        usleep          10000      10086         86
        nanosleep       10000      10091         91
        select          10000      10089         89
        pselect         10000      10088         88
--------------------------------
        usleep           1000       1089         89
        nanosleep        1000       1065         65
        select           1000       1065         65
        pselect          1000       1066         66
--------------------------------
        usleep            900        969         69
        nanosleep         900        974         74
        select            900        970         70
        pselect           900        980         80
--------------------------------
        usleep            500        569         69
        nanosleep         500        565         65
        select            500        569         69
        pselect           500        569         69
--------------------------------
        usleep            100        166         66
        nanosleep         100        165         65
        select            100        163         63
        pselect           100        163         63
--------------------------------
        usleep             10         73         63
        nanosleep          10         76         66
        select             10         73         63
        pselect            10         78         68
--------------------------------
        usleep              1         64         63
        nanosleep           1         66         65
        select              1         65         64
        pselect             1         63         62
--------------------------------
4、测试代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
 
 
int main(int argc, char **argv)
{
    unsigned int nTimeTestSec = 0;
    unsigned int nTimeTest = 0;
    struct timeval tvBegin;
    struct timeval tvNow;
    int ret = 0;
    unsigned int nDelay = 0;
    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; //误差
 
    fprintf(stderr, "%19s%12s%12s%12s\n", "fuction", "time(usec)", "realtime", "reduce");
    fprintf(stderr, "----------------------------------------------------\n");
    for (i = 0; i < 20; i++)
    {
        if (delay[i] <= 0)
            break;
        nDelay = delay[i];
        //test sleep
        gettimeofday(&tvBegin, NULL);
        ret = usleep(nDelay);
        if(ret == -1)
        {
            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
         req.tv_sec = nDelay/1000000;
         req.tv_nsec = (nDelay%1000000) * 1000;
 
         gettimeofday(&tvBegin, NULL);
         ret = nanosleep(&req, NULL);
         if (-1 == ret)
         {
            fprintf (stderr, "\t nanousleep   %8u   not support\n", nDelay);
         }
         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
         tv.tv_sec = 0;
         tv.tv_usec = nDelay;
 
         gettimeofday(&tvBegin, NULL);
         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);
 
         //pselcet
         req.tv_sec = nDelay/1000000;
         req.tv_nsec = (nDelay%1000000) * 1000;
 
         gettimeofday(&tvBegin, NULL);
         ret = pselect(0, NULL, NULL, NULL, &req, NULL);
         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 pselect      %8u   %8u   %8d\n", nDelay, nTimeTest,nReduce);
 
         fprintf (stderr, "--------------------------------\n");
 
    }
    
    return 0;
}

参考博客:https://www.jianshu.com/p/42abcc2c9e50

你可能感兴趣的:(linux)