2014-11-04 95 views
0

我想實現一個後臺用戶空間程序,它將在Linux中每100ms執行一次各種任務和計算。我可以通過在Linux中使用報警信號來實現這一點,下面的結構是我實現間隔計時器的方式。在Linux中使用C++實現低開銷間隔計時器

void timer_handler (int signum){ 
    printf("In timer handler!\n"); 
} 

int main(){ 

    struct sigaction s_action; 
    struct itimerval timer; 

    /* Set Up a Timer */ 
    /* Install timer_handler as the signal handler for SIGVTALRM. */ 
    memset (&s_action, 0, sizeof (s_action)); 
    s_action.sa_handler = &timer_handler; 
    sigaction (SIGVTALRM, &s_action, NULL); 

    /* Timer configuration for 100ms */ 
    timer.it_value.tv_sec = 0; 
    timer.it_value.tv_usec = 100000; 
    timer.it_interval.tv_sec = 0; 
    timer.it_interval.tv_usec = 100000; 

    /* Set up the timer */ 
    setitimer (ITIMER_VIRTUAL, &timer, NULL); 

    while(1); 
} 

但是,由於無限循環,這種方法似乎不是最佳的方法(就性能而言)。它顯着增加了CPU利用率。一旦它開始在後臺運行,我的其他程序的性能會下降15%。

我最想要的是有一個程序,除非發生定時器中斷,否則會保持睡眠狀態。多線程似乎是一種選擇,但我對這個主題並不很有經驗。我將不勝感激任何有關如何以最小的開銷實施此類計劃的建議或指示。

+1

如果你想讓你的程序進入睡眠狀態,爲什麼不調用sleep()? – 2014-11-04 20:00:08

+0

我首先嚐試睡眠,但沒有奏效。使用sleep()或nanosleep(),我的定時器處理程序似乎從未觸發。我從警報(2)手冊頁讀取了sleep()可能會干擾SIGALRM信號。 – jake 2014-11-04 21:59:26

回答

0

閱讀time(7),​​,timerfd_create(2)poll(2)nanosleep(2)Advanced Linux Programming

您的信號處理程序不正確(它不應該調用printf;它可能是write)。

你可以有

while(1) poll(NULL, 0, 1); 

但可能與timerfd_create初始化文件描述符使用poll真實的事件循環應該會更好。

我假設你當然相信每個週期性任務的持續時間要比這個週期少得多。 (例如,每個任務需要不超過50毫秒但是具有100毫秒的時間)。

+1

我認爲我的問題主要是由於我用setitimer使用的標誌(ITIMER_VIRTUAL),它只在進程處於活動狀態時才計數。將它切換到ITIMER_REAL並按照您的建議輪詢NULL文件描述符似乎會導致100ms間隔的非常低的開銷。也非常感謝參考資料。 – jake 2014-11-04 22:35:45