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原始碼:
https://github.com/eyjian/libmooon/blob/master/src/sys/event.cpp |
相關文章
- 聊聊select, poll 和 epoll_waitAI
- Linux中Sleep和Wait命令的使用方式LinuxAI
- IO模式 select、poll、epoll模式
- select、poll、epoll之間的區別
- 《UNIX網路程式設計》筆記 - select和poll程式設計筆記
- IO多路複用(一)– Select、Poll、Epoll
- Linux IO模式及 select、poll、epoll詳解(含部分例項原始碼)Linux模式原始碼
- 多路I/O複用:select、poll、epoll(二)
- 伺服器IO多路複用的select和poll的區別以及監聽套接字select函式的四個宏操作伺服器函式
- Linux中select()函式分析Linux函式
- IO多路複用——深入淺出理解select、poll、epoll的實現
- selec和poll的區別
- linux系統下poll和epoll核心原始碼剖析Linux原始碼
- 一文說透IO多路複用select/poll/epoll
- Linux select()Linux
- java yield()和sleep()的區別Java
- select into from 和 insert into select 的用法和區別
- sleep()和wait()區別AI
- 面試官:select、poll、epoll有何區別?我:阿巴阿巴...面試
- select * 和 select 所有欄位的區別
- JQuery 獲取select被選中的value和textjQuery
- java nio中的select和channel是怎麼使用的?Java
- DataTable中的select()用法
- SQLite中的SELECT子句SQLite
- Task.Delay 和 Thread.Sleep 的區別thread
- Systrace 執行緒 CPU 執行狀態分析技巧 - Sleep 和 Uninterruptible Sleep 篇執行緒
- vue中select的使用以及select設定預設選中Vue
- 在 .NET 中的 ConvertAll 和 Select 方法哪個效能好
- 【Java】sleep和wait區別總結JavaAI
- 面試題總結:Queue 中 poll()和 remove()有什麼區別?面試題REM
- SQL Server中的SELECT會阻塞SELECT相關資料SQLServer
- 深入理解SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE
- 淺談Golang中select的用法Golang
- golang當中對select的理解Golang
- 解析MySQL中INSERT INTO SELECT的使用MySql
- Linux中“>”和“>>”的區別Linux
- MySql 中 select 使用MySql
- Latch的spin及sleep(zt)