非實時系統精確定時器的實現

2021-07-11 17:35:17 字數 927 閱讀 5792

我們通常使用的系統,不管是linux還是windows,都是非實時系統。非實時系統可以獲得很精確的當前時間,甚至可以通過讀取cpu的某些暫存器得到以cpu週期計數的時鐘,估計除了gps系統之外足以應付我們日常能夠碰到的應用,但是,非實時系統並沒有提供精確的定時器實現。如果在linux或者windows系統中使用系統定時器,儘管我們可以建立精度為1ms甚至更小的定時器,但是實際執行的時候可以發現,定時器總是需要幾ms甚至十幾ms才會被排程一次,而不能達到期望的精度。

通常情況下10ms量級的定時器可以滿足應用的需求,但一些特殊場景下10ms就顯得太長了,比如我碰到過乙個場景,在乙個單向網路上將資料推動到一台裝置上,推送速率大約100mbps量級。如果每10ms推送一次,那麼每次推送的資料量大約是1mb,可是那個接收裝置比較老,沒有這麼大的接收buffer,很容易造成丟包,而單向網路上是沒有辦法進行資料重傳的,如果我們降低一次推送的資料量,那麼總體的傳輸效率就會相應下降。因此,唯一可行的方法是我們根據接收裝置的io大小,盡可能「平滑」的進行資料的推送,我們需要更精細的時鐘對推送行為進行控制。

對於linux系統,理論上我們可以重新編譯核心,減少系統時鐘的呼叫間隔,但這樣做動靜太大,可能影響許多系統模組的執行,存在風險,我們還是期望能夠在應用層解決問題。經過嘗試,最終我們找到了問題的解決方案:

感謝cpu廠商為我們提供的多核系統,我們犧牲乙個核心,在這個核上跑乙個忙等待的檢查執行緒,它的作用就是用死迴圈的方式不斷的讀取系統時間,並通知推送執行緒(可以是多個)是否可以啟動推送。推送執行緒平時等待在乙個訊號量上,當時間到期之後,檢查執行緒置位訊號量,推送執行緒被啟用並進行推送。按照這個方式,我們可以實現幾乎任意精度的定時器。

這個方案的缺點是有乙個cpu核心被浪費了,好在伺服器一般都有4、8甚至16個核心,浪費乙個核的代價還是可以接受的。

注:我們為該方案申請了專利並已經獲得授權,專利名稱:一種在非實時系統上精確網路限速的方法,授權號cn102368729b。

linux使用select實現精確定時器詳解

自 本文講述如何使用select實現超級時鐘。使用select函式,我們能實現微妙級別精度的定時器。同時,select函式也是我們在編寫非阻塞程式時經常用到的乙個函式 在編寫程式時,我們經常會用到定時器。首先看看select函式原型如下 如下 int select int nfds,fd set r...

乙個精確的定時器

typedef union large integer longlong quadpart 8位元組整型數 large integer large integer litmp longlong qpart1,qpart2 double dfminus,dffreq,dftim queryperfor...

精確到1ms的定時器

settimer 設定的定時器的定時時間 50ms,這在實時資料採集中是不夠的。用多 定時器能精確到1ms,效果很好。定時器 define timer accuracy 1 int timerid uint waccuracy int inittimer int releasetimer void ...