2012-06-20 129 views
3

我有一個程序需要每X秒執行一次寫入輸出。程序會在每個輸出之間進行一些間歇輪詢和處理。因此,例如,我可能每5秒輸出一次,但我醒來後每隔1秒輪詢一次,直到我擊中下一個5秒刻度。理論上的程序將在重啓之間運行數月,甚至可能更長。Linux/c + +計時方法,每N秒鐘執行一次,儘管漂移?

我需要每X秒執行一次以保持與掛鐘一致。換句話說,我不能讓時鐘漂移讓我擺脫X秒標記。我不需要完全相同級別的輪詢中的準確性,但我想更頻繁地輪詢一秒鐘,所以我需要一個能夠代表次秒級精度的結構。

我意識到,由於在OS上運行的本質,任何計時器的執行都會有一定的不一致/延遲,因此我不能確定我會在處執行有史以來x秒。但是,這很好,只要它保持一個小的正態分佈,我不想要的是讓漂移讓時間持續地越來越遠。

我也希望儘可能地儘量減少輪詢的CPU成本,但這是次要的問題。

哪些時序結構可用於Linux,最能爲我提供這種級別的準確性?我試圖避免在分發中包含麻煩的應用程序中的提升,但如果必須的話可以使用它。因此,使用標準C++庫的方法是首選,但如果Bosst可以做得更好,我也想知道。

謝謝。

-ps,我不能使用C++ 11。這不是一種選擇,所以我無法使用任何構造。

+0

什麼是您的硬件平臺?您是否計劃針對您的應用程序運行實時內核和實時調度? – Chad

+0

另外,你想從'boost'期待什麼「分配麻煩」?如果您靜態鏈接到它,則無需部署/分發。 – Chad

+0

我沒有實時運行。定期redhawk Linux(可能)。我不需要實時的祕密,只是爲了避免漂移。 – dsollen

回答

4

clock_gettimeclock_nanosleep兩者上操作的子第二次,和使用CLOCK_MONOTONIC應防止任何歪斜由於調整系統時間(如NTP或adjtimex)。例如,

long delay_ns = 250000000; 
struct timespec next; 
clock_gettime(CLOCK_MONOTONIC, &next); 
while (1) { 
    next.ts_nsec += delay_ns; 
    next.ts_sec += ts_nsec/1000000000; 
    next.ts_nsec %= 1000000000; 
    clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL); 
    /* do something after the wait */ 
} 

在現實中,你應該覈實是否已因信號回來得早,因爲太多的時間過去了,而你睡覺,你是否應該跳過的間隔。

其他睡眠方法,如nanosleepselect,只允許指定一個時間間隔並使用CLOCK_REALTIME,這是系統時間,可能會改變。

+2

據此:http://stuff.onse.fi/man?program=clock_gettime§ion=3 CLOCK_MONOTONIC_RAW是需要用來避免由於NTP等引起的時間變化。 – Chad

+0

這是一個很好的答案。一個跟進問題,但。我實際上可能希望在事件發生時提前打印,這樣讀取文件的時間就會持續下去(仍然試圖在工作中獲得反饋)。我想我可以做到這一點,只是通過使用不同的常數傳遞給時鐘方法,如果我需要的話? – dsollen

0

我開始記錄時間t_0,然後在任何給定時間t,如果i = (t - t_0)/X(整數除法)大於上次執行的相同數量,則再次執行。

例如,假設您每5秒運行一次,如果您在23時開始記錄i = 0, t_0 = 23。然後在27時,(27 - 23)/5 = 0,所以你還沒有執行。但下一次,當涉及到時間28,(28 - 23)/5 = 1,這是大於0,所以你執行。

這樣你就不會在計數器中增加每個可能產生巨大漂移的刻度,你絕對計算自啓動以來的時間,因此你知道執行的確切時間。

+0

更好的是,計算直到下一次運行的時間,並使用睡眠函數('select'或類似的便攜式亞秒睡眠)。但關鍵是使用當前時間和上次預定時間後5秒,而不是當前時間5秒。 –

+0

時間只有一秒鐘,但不是嗎?那可以讓至少一秒鐘的變化不是嗎?另外,這是否意味着每次我做到系統調用或者C是否抽象出系統調用的需求? – dsollen

+0

'select'給亞秒睡眠。 –

1

如果您需要一些精確的時序而沒有抖動或時鐘漂移,請確保有外部時間源,如GPS,原子鐘或無線電時鐘。 參見例如在PDF中記錄的NTP集成。 所有的NTP技巧都可以在Linux上運行,就像NanoBSD(PDF格式)一樣。