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

160 篇文章 ¥69.90 ¥99.00
本文介绍了Linux中几种延时函数sleep、usleep、nanosleep、select和pselect的使用和区别。它们分别以秒、微秒和纳秒为单位提供暂停功能。在精确度对比中,usleep和nanosleep在低精度场景下表现接近,而在高精度场景下,所有函数表现相当。注意使用这些函数时要处理可能的信号中断。文章提供了测试代码供参考。

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

1、简介

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

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

nanosleep( )---------以纳秒为单位
#include<time.h>
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<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>
#include<sys/select.h>
 
 
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 延时函数的使用方法 在Linux系统中,延时函数可以分为 **用户空间延时函数** 和 **内核空间延时函数** 两种类型。不同的场景下应选择合适的延时函数以满足时间精度和资源占用的需求。 #### 用户空间延时函数 适用于应用程序开发,主要包含以下几种: 1. `sleep(unsigned int seconds)` - 功能:使进程休眠指定的秒数。 - 精度:秒级。 - 示例: ```c sleep(2); // 延时2秒 ``` 2. `usleep(unsigned long usec)` - 功能:使进程休眠指定的微秒数。 - 精度:微秒级(1秒=1,000,000微秒)。 - 示例: ```c usleep(1000000); // 延时1秒 ``` 3. `nanosleep(const struct timespec *req, struct timespec *rem)` - 功能:提供纳秒级别的高精度延时。 - 精度:纳秒级(1秒=1,000,000,000纳秒)。 - 示例: ```c struct timespec ts = {1, 500000000}; // 1秒500,000,000纳秒 nanosleep(&ts, NULL); ``` 4. `select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)` - 功能:通过设置超时参数实现延时。 - 精度:微秒级。 - 示例: ```c struct timeval tv = {2, 0}; // 2秒 select(0, NULL, NULL, NULL, &tv); ``` 5. `pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)` - 功能:类似于`select`,但支持更精确的超时控制(纳秒级)。 - 精度:纳秒级。 - 示例: ```c struct timespec ts = {1, 500000000}; // 1秒500,000,000纳秒 pselect(0, NULL, NULL, NULL, &ts, NULL); ``` #### 内核空间延时函数 适用于编写设备驱动程序或内核模块,主要包括以下几种: 1. `ndelay(unsigned long nsecs)` - 功能:纳秒级别的忙等待延时。 - 精度:纳秒级。 - 适用范围:短时间延时(通常小于几纳秒)。 - 示例: ```c ndelay(100); // 延时100纳秒 ``` 2. `udelay(unsigned long usecs)` - 功能:微秒级别的忙等待延时。 - 精度:微秒级。 - 适用范围:短时间延时(通常小于200微秒)。 - 示例: ```c udelay(100); // 延时100微秒 ``` 3. `mdelay(unsigned long msecs)` - 功能:毫秒级别的忙等待延时。 - 精度:毫秒级。 - 适用范围:较长时间延时(通常大于200微秒)。 - 示例: ```c mdelay(100); // 延时100毫秒 ``` 4. `ssleep(unsigned int seconds)` - 功能:秒级别的睡眠延时。 - 精度:秒级。 - 优点:不占用CPU资源。 - 缺点:时间精度较低。 - 示例: ```c ssleep(2); // 延时2秒 ``` 5. `msleep(unsigned int msecs)` - 功能:毫秒级别的睡眠延时。 - 精度:毫秒级。 - 优点:不占用CPU资源。 - 缺点:时间精度较低。 - 示例: ```c msleep(100); // 延时100毫秒 ``` #### 使用建议 - **对于高精度要求**:优先使用`nanosleep`或内核中的`ndelay`、`udelay`等函数。 - **对于低精度要求**:使用`sleep`、`usleep`、`ssleep`、`msleep`等函数。 - **避免长时间忙等待**:忙等待会消耗大量CPU资源,适合短时间延时;长延时应使用睡眠函数[^1]。 ### 示例代码 ```c #include <stdio.h> #include <unistd.h> int main(void) { int i = 10; while (i--) { sleep(2); // 延时2秒 printf("Sleep 2s!\n"); usleep(1000000); // 延时1秒 printf("Sleep 1000000us!\n"); } return 0; } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值