在进行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++常用封装:
- 基于nanosleep的毫秒级封装
#include <time.h>
void millisleep(uint32_t milliseconds) {
struct timespec ts = {
milliseconds / 1000,
(milliseconds % 1000) * 1000000
};
while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));
}
- 基于nanosleep的微秒级封装
#include <time.h>
void microsleep(uint32_t microseconds) {
struct timespec ts = {
microseconds / 1000000,
(microseconds % 1000000) * 1000
};
while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));
}
- 基于poll的秒级封装
// 可libco协程库中安全使用
void pollsleep(int milliseconds) {
(void)poll(NULL, 0, milliseconds);
}
- 基于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++标准库提供的:
- 毫秒睡眠
#if __cplusplus >= 201103L
#include <chrono>
#include <system_error>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
#endif // __cplusplus >= 201103L
- 微秒睡眠
#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源码:
https://github.com/eyjian/libmooon/blob/master/src/sys/event.cpp