专栏首页蓝天Linux中的sleep、usleep、nanosleep、poll和select

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
void millisleep(uint32_t milliseconds) {
struct timespec ts = {
milliseconds / 1000,
(milliseconds % 1000) * 1000000
};
while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));
}

2) 基于nanosleep的微秒级封装

#include
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
#include
#include
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#endif // __cplusplus >= 201103L

6) 微秒睡眠

#if __cplusplus >= 201103L
#include
#include
#include
std::this_thread::sleep_for(std::chrono::microseconds(1000));
#endif // __cplusplus >= 201103L

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

https://github.com/eyjian/libmooon/blob/master/src/sys/event.cpp

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C#脚本实践(三): 集成到游戏

    至此, C#做为脚本已经完全可行了: 可嵌入, 跨平台, 高效率, 热更新, 几乎可以忽略的编译时间, 强大的IDE支持, 丰富的第三方库, 部分动态语言特性的...

    逍遥剑客
  • Lua和C如何交互(一)

    全局表中存放了name和hello world的对应关系, 可以通过name在全局表中找到对应的hello world

    程序手艺人
  • JNI入门

    首先声明一点,Eclipse不仅仅适合于开发Java应用程序。Eclilpse为Java开发提供了极好的支持,它的设计初衷也是为了Java。但得益于它的设计架构...

    刘晓杰
  • 修复miniblink 文件编码检测和退出内存泄漏的bug

    文本检测的bug原因是我把icu整个都端了,自然icu里检测编码的好用接口也废弃了。不过我扣了一部分出来,用于检测UTF8和GBK编码。剩下的编码,经海绵宝宝

    龙泉寺扫地僧
  • C++ list

    [work@db-testing-com06-vm3.db01.baidu.com c++]$ g++ -o list list.cpp 

    阳光岛主
  • 关于Web3D

    逍遥剑客
  • 从公有云上导镜像导私有云环境

    要求环境上的机器有访问公网的能力,同时安装的docker版本最低为1.12.6,推荐使用的版本为17.12.1(或者以上)

    用户1502070
  • 2018年的经历有苦有甜

    2018年每周的任务,目标都通过Trello一直记录着,看板的形式非常直观,目标清晰,同时也能看到自己在某一方面的时间投入和支出。这也是工作之后一直坚持使用...

    程序手艺人
  • 命名空间及模块化

    Java用package来达到命名空间同样的效果。 C++就有对应关键字:using namespace。 JavaScript库用对象来封装命名空间。

    城市中的游牧民族
  • C/C++常见错误汇总

    出错原因: main.cpp中没有找到对应的函数名声明,没有在.cpp引用包含该函数名的头文件.h。 解决方法: 引入对应头文件。

    城市中的游牧民族

扫码关注云+社区

领取腾讯云代金券