在進行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源碼:
https://github.com/eyjian/libmooon/blob/master/src/sys/event.cpp |