首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Muduo網絡編程示例之三:高精度定時器與 Timerfd 實踐

     編輯:關於C語言

Linux 時間函數選型

在服務端程式中,時間相關任務主要有三類:獲取當前時間、時區/日期計算、定時操作。Muduo 的選型原則:

  • 計時:僅使用 gettimeofday()(微秒精度,x86-64 上為 vsyscall,無內核切換開銷)
  • 定時:僅使用 timerfd_* 系列(將定時器轉為檔案描述符,無縫融入 epoll,統一處理 IO 與超時事件)

拒絕 sleep、alarm、timer_create 等基於信號的介面,因多線程下信號處理極其棘手;也拒絕阻塞式 nanosleep,違背非阻塞網絡編程原則。

Muduo EventLoop 定時器介面

typedef boost::function<void()> TimerCallback;

TimerId runAt(const Timestamp& time, const TimerCallback& cb);   // 指定時刻
TimerId runAfter(double delay, const TimerCallback& cb);         // 延遲執行
TimerId runEvery(double interval, const TimerCallback& cb);      // 週期執行
// void cancel(TimerId timerId); // 尚未實現

所有回呼均在 EventLoop 所在線程執行,與網絡事件回呼同線程,避免併發問題。內部 TimerQueue 採用鏈表實現,適合定時器數量較少(<10)的場景;大量定時器建議改用二叉堆優化。

Boost.Asio 風格定時器示例移植

Muduo 重新實現了 Asio 教程中的四個定時器示例:

  1. timer2:非阻塞定時
  2. timer3:回呼傳遞參數
  3. timer4:成員函數作為回呼
  4. timer5/6:多線程回呼與鎖優化

以 timer4 為例,展示如何用 boost::bind 綁定成員函數實現週期性列印:

class Printer : boost::noncopyable
{
public:
    Printer(EventLoop* loop) : loop_(loop), count_(0)
    {
        loop_->runAfter(1, boost::bind(&Printer::print, this));
    }
    ~Printer() { std::cout << "Final count is " << count_ << "\n"; }

    void print()
    {
        if (count_ < 5)
        {
            std::cout << count_ << " ";
            ++count_;
            loop_->runAfter(1, boost::bind(&Printer::print, this));
        }
    }
private:
    EventLoop* loop_;
    int count_;
};

時間精度與現實考量

Linux 非即時系統,用戶態無法達成完全精確可控的計時;但透過 timerfd 納秒級精度、控制 CPU 負載,可在 99.99% 情況下滿足工程需求。閏秒、時鐘跳變等進階主題留待專題文章探討。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved