在進(jìn)行Linux C/C++編程時(shí)袖迎,可調(diào)用的sleep函數(shù)有好多個(gè)冕臭,那么究竟應(yīng)當(dāng)調(diào)用哪一個(gè)了腺晾?下表列出了這幾個(gè)函數(shù)間的異同點(diǎn),可作為參考:
性質(zhì) | 精準(zhǔn)度 | 線程安全 | 信號(hào)安全 | ||
---|---|---|---|---|---|
sleep | libc庫函數(shù) | 秒 | 是 | 不能和alarm同時(shí)使用 | 有些是基于alarm實(shí)現(xiàn)的辜贵,所以不能和alarm同 |
usleep | libc庫函數(shù) | 微秒 | - | - | POSIX.1-2001已將usleep標(biāo)注為廢棄悯蝉,POSIX.1-2008已刪除usleep,應(yīng)當(dāng)使用nanosleep替代usleep |
nanosleep | 系統(tǒng)調(diào)用 | 納秒 | 是 | 不確定 | 即使被信號(hào)中斷托慨,也可實(shí)現(xiàn)實(shí)際睡眠時(shí)長(zhǎng)不小于參數(shù)指定時(shí)長(zhǎng) |
clock_nanosleep | 系統(tǒng)調(diào)用 | 納秒 | 是 | 不確定 | 區(qū)別于nanosleep鼻由,可選擇為相對(duì)或絕對(duì)時(shí)間,其次是可以選擇使用哪個(gè)時(shí)鐘 |
poll | 系統(tǒng)調(diào)用 | 毫秒 | 是 | 是 | 在協(xié)程庫libco中可安全使用厚棵,如被信號(hào)中斷蕉世,則實(shí)際睡眠時(shí)長(zhǎng)會(huì)小于參數(shù)指定的時(shí)長(zhǎng) |
ppoll | 系統(tǒng)調(diào)用 | 納秒 | 是 | 是 | 如被信號(hào)中斷,則實(shí)際睡眠時(shí)長(zhǎng)會(huì)小于參數(shù)指定的時(shí)長(zhǎng) |
select | 系統(tǒng)調(diào)用 | 微秒 | 是 | 是 | 即使被信號(hào)中斷婆硬,也可實(shí)現(xiàn)實(shí)際睡眠時(shí)長(zhǎng)不小于參數(shù)指定時(shí)長(zhǎng) |
pselect | 系統(tǒng)調(diào)用 | 納秒 | 是 | 是 | 如被信號(hào)中斷狠轻,則實(shí)際睡眠時(shí)長(zhǎng)會(huì)小于參數(shù)指定的時(shí)長(zhǎng) |
C/C++常用封裝:
- 基于nanosleep的毫秒級(jí)封裝
#include <time.h>
void millisleep(uint32_t milliseconds) {
struct timespec ts = {
milliseconds / 1000,
(milliseconds % 1000) * 1000000
};
while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));
}
- 基于nanosleep的微秒級(jí)封裝
#include <time.h>
void microsleep(uint32_t microseconds) {
struct timespec ts = {
microseconds / 1000000,
(microseconds % 1000000) * 1000
};
while ((-1 == nanosleep(&ts, &ts)) && (EINTR == errno));
}
- 基于poll的秒級(jí)封裝
// 可libco協(xié)程庫中安全使用
void pollsleep(int milliseconds) {
(void)poll(NULL, 0, milliseconds);
}
- 基于select的毫秒級(jí)封裝
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;
}
}
如果開發(fā)環(huán)境是C++11或更高版本,則可直接使用C++標(biāo)準(zhǔn)庫提供的:
- 毫秒睡眠
#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函數(shù)均不方便控制它們提前結(jié)束彬犯,如果需要這種sleep向楼,可基于pthread_cond_timedwait實(shí)現(xiàn),實(shí)現(xiàn)可參考CEvent源碼:
https://github.com/eyjian/libmooon/blob/master/src/sys/event.cpp
轉(zhuǎn)自:https://blog.csdn.net/aquester/article/details/86651206