岚天逸见

Linux中的sleep、usleep、nanosleep、poll和select

在进行Linux C/C++编程时,可调用的sleep函数有好多个,那么究竟应当调用哪一个了?下表列出了这几个函数间的异同点,可作为参考:

 

性质

精准度

线程安全

信号安全

 

sleep

libc库函数

不能和alarm同时使用

有些是基于alarm实现的,所以不能和alarm同时使用

usleep

libc库函数

微秒

-

-

POSIX.1-2001已将usleep标注为废弃,POSIX.1-2008已删除usleep,应当使用nanosleep替代usleep

nanosleep

系统调用

纳秒

不确定

即使被信号中断,也可实现实际睡眠时长不小于参数指定时长

clock_nanosleep

系统调用

纳秒

不确定

区别于nanosleep,可选择为相对或绝对时间,其次是可以选择使用哪个时钟

poll

系统调用

毫秒

在协程库libco中可安全使用,如被信号中断,则实际睡眠时长会小于参数指定的时长

ppoll

系统调用

纳秒

如被信号中断,则实际睡眠时长会小于参数指定的时长

select

系统调用

微秒

即使被信号中断,也可实现实际睡眠时长不小于参数指定时长

pselect

系统调用

纳秒

如被信号中断,则实际睡眠时长会小于参数指定的时长

 

C/C++常用封装:

1) 基于nanosleep的毫秒级封装

#include <time.h>

void millisleep(uint32_t milliseconds) {

    struct timespec ts = {

        milliseconds / 1000,

        (milliseconds % 1000) * 1000000

    };

    while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));

}

 

2) 基于nanosleep的微秒级封装

#include <time.h>

void microsleep(uint32_t microseconds) {

    struct timespec ts = {

        microseconds / 1000000,

        (microseconds % 1000000) * 1000

    };

    while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));

}

 

3) 基于poll的秒级封装

// 可libco协程库中安全使用

void pollsleep(int milliseconds) {

    (void)poll(NULL, 0, milliseconds);

}

 

4) 基于select的毫秒级封装

void selectsleep(int milliseconds) {

    struct timeval timeout = {

        milliseconds / 1000,

        (milliseconds % 1000)

    };

    struct timeval old_timeout = { timeout.tv_sec, timeout.tv_usec };

    while (true) {

        (void)select(0, NULL, NULL, NULL, &timeout);

        if (timeout.tv_sec<=0 && timeout.tv_usec<=0)

            break;

    }

}

 

如果开发环境是C++11或更高版本,则可直接使用C++标准库提供的:

5) 毫秒睡眠

#if __cplusplus >= 201103L

#include <chrono>

#include <system_error>

#include <thread>

 

std::this_thread::sleep_for(std::chrono::milliseconds(1000));

#endif // __cplusplus >= 201103L

 

6) 微秒睡眠

#if __cplusplus >= 201103L

#include <chrono>

#include <system_error>

#include <thread>

 

std::this_thread::sleep_for(std::chrono::microseconds(1000));

#endif // __cplusplus >= 201103L

 

上述介绍的sleep函数均不方便控制它们提前结束,如果需要这种sleep,可基于pthread_cond_timedwait实现,实现可参考CEvent源码:

posted on   岚天逸见  阅读(3857)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义

导航

统计信息

点击右上角即可分享
微信分享提示