Linux下的timerfd在OS X下可以用什麼替代?

有一段代碼要從Linux遷移到OS X下,但是在timerfd上出了點問題,Google了很久也沒有找到解決方案。


取決於你現在使用timerfd的代碼是怎麼寫的。

如果你還是想用read/select來獲取timeout,你可以單獨起一個線程來模擬timerfd的功能,再用pipe(2)來替換原來的 timerfd,時間到了就往pipe里寫8個位元組。

或者把timer的功能做到 reactor 里,控制 poll() 的第3個參數來實現 timer。可參考 muduo/backport.diff at master · chenshuo/muduo · GitHub


前幾天剛好看到這份代碼,下載這份代碼搜索timerfd.

GitHub - vonnyfly/tgt

並不需要多線程。

用setitimer + sigaction 來實現。


謝謝@陳碩 大大的問答,事實上最近的確在看《Linux 多線程伺服器編程——使用muduo C++網路庫》。

單獨起一個線程的方案,自己寫了個小類粗糙地封裝了一下,自己提的問題還是把自己的代碼貼上來吧,可能有錯誤哈:

//C++11
//TimerFd.h
class TimerFd
: public boost::noncopyable
{
private:
int pipeFd_[2];
std::atomic& isTiming_;
public:
TimerFd();
~TimerFd();

int GetFd() const;
void SetTime(const std::chrono::milliseconds timeout);
};

//TimerFd.cpp
TimerFd::TimerFd()
: isTiming_(false)
{
if(::pipe(pipeFd_) == -1)
{
LOG_FATAL &<&< "TimerFd not available."; } } TimerFd::~TimerFd() { ::close(pipeFd_[1]); ::close(pipeFd_[0]); } int TimerFd::GetFd() const { return pipeFd_[0]; } void TimerFd::SetTime(const std::chrono::milliseconds timeout) { if(isTiming_) { LOG_ERROR &<&< "Timer is running."; return; } auto timeoutMs = static_cast&(timeout.count());
isTiming_ = true;
std::thread timer([this, timeoutMs]()
{
::poll(nullptr, 0, timeoutMs);
::write(pipeFd_[1], " ", 1);
isTiming_ = false;
});
timer.detach();
}

在OS X下需要timerfd的初衷就是希望使定時器能和select、poll這些函數配合,現在通過這種比較簡單的方法基本實現了這個目的,有知友提到此方案由於線程的開銷可能會對計時精度造成影響,在我的MacBook(Intel Core i7 4@2.8GHz, 16GB)下測試計時誤差基本在萬分之四以內,本來也是自己寫著練手的小項目,這種精度應該足矣。至於timing wheel等方案,我現在只是知道大概原理,以後再試著加入吧。


推薦閱讀:

生信自學之linux操作基礎
為什麼拷貝到U盤速度越來越慢?
Linux系統安全
【技術人快報189期】Linux補丁是「完全無用的垃圾」+上海銀行探索智能運維

TAG:Mac | macOS | Linux | OSX開發 |