2013-11-03 83 views
3

我想有一個信號處理程序停止計時器而不退出我的程序。我該怎麼去。我想StopTimer來處理信號,停止計時信號處理程序停止計時器在C

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <sys/time.h> 
#include <signal.h> 
#include <unistd.h> 

#define INTERVAL 2  // number of seconds to go off 

int main(int argc, char* argv[]) { 

TimerSet(INTERVAL); 

while(1) 
{ 
    // do stuff 
} 
return 0; 
} 

void TimerSet(int interval) 
{ 
printf("starting timer\n"); 
struct itimerval it_val; 

// interval value 
it_val.it_value.tv_sec = interval; 
it_val.it_interval = it_val.it_value; 

// on SIGALRM, close window 
if (signal(SIGALRM, TimerStop) == SIG_ERR) 
{ 
    perror("Unable to catch SIGALRM"); 
    exit(1); 
} 

// set interval timer, returns SIGALRM on expiration 
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) 
{ 
    perror("error calling setitimer()"); 
    exit(1); 
} 
} 

void TimerStop(int signum) 
{ 
printf("Timer ran out! Stopping timer\n"); 
exit(signum); 
} 

我試圖setitimer時間間隔設置爲0,但我不知道如何使用相同的計時器TimerStop信號處理函數

+2

在調用'signal()'之前,只需將'it_interval'設置爲零,並且您將獲得一次性計時器,並且您不必在處理程序中執行任何操作。 –

+1

在調用'setitimer()'之前,而不是'signal()'。你也從來沒有設置'struct itimerval'的'tv_usec'成員,這是不好的。 –

+0

您不應該在信號處理程序中使用fprintf()和朋友。 fprintf()不是信號安全的。 – wildplasser

回答

2

只需將it_interval設置爲零,即可獲得一次性計時器。你不需要在你的處理程序中對它做任何事情。

例如,對於這樣的:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <sys/time.h> 
#include <signal.h> 
#include <unistd.h> 

#define INTERVAL 2    // number of seconds to go off 

void TimerStop(int signum) { 
    printf("Timer ran out! Stopping timer\n"); 
} 

void TimerSet(int interval) { 
    printf("starting timer\n"); 
    struct itimerval it_val; 

    it_val.it_value.tv_sec = interval; 
    it_val.it_value.tv_usec = 0; 
    it_val.it_interval.tv_sec = 0; 
    it_val.it_interval.tv_usec = 0; 

    if (signal(SIGALRM, TimerStop) == SIG_ERR) { 
     perror("Unable to catch SIGALRM"); 
     exit(1); 
    } 
    if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { 
     perror("error calling setitimer()"); 
     exit(1); 
    } 
} 

int main(int argc, char *argv[]) { 

    TimerSet(INTERVAL); 

    while (1) { 
     // do stuff 
    } 
    return 0; 
} 

消息"Timer ran out! Stopping timer"將只出現一次,而你的定時器將停止沒有你做任何事情。

請注意,您需要填寫struct itimervaltv_usec成員,您當前的代碼不能執行此操作。如果你不這樣做,it_interval是不太可能爲零,你的計時器永遠不會停止。

printf()與其他標準IO函數一起,從信號處理程序調用並不是真的安全,但在這種特殊情況下,它不會引起任何問題,因爲主代碼只是坐在一個循環中,沒有做任何事情。

此外,假設您有意打電話signal() - sigaction()是設置處理程序的推薦方式。 setitimer()現在也已過時,建議使用timer_settime()

+0

我想讓我的計時器稍後在我的程序中的某個點運行。我做了全局的it_val,並有一個函數來改變時間間隔。但是,計時器永遠停止。當我需要時,如何讓計時器開啓和關閉? setitimer只能運行一次。 – Olivier

+0

是什麼讓你覺得'setitimer()'只能運行一次?你可以通過調用'setitimer()'使其全部爲零,然後通過調用其他東西來繼續。 –

+0

你是對的,我一定早點做錯了。這工作。謝謝 – Olivier

2

根據內手動:

Timers decrement from it_value to zero, generate a signal, and reset to 
    it_interval. A timer which is set to zero (it_value is zero or the timer 
    expires and it_interval is zero) stops. 

    Both tv_sec and tv_usec are significant in determining the duration of a 
    timer. 

所以定時器可以設置,如果間隔setitimer()調用之前設置爲零(由於鴨的評論),只運行一次。

+0

我得到這個錯誤:調用setitimer()的錯誤:無效的參數。 當試圖停止計時器。當我將間隔設置爲0時,它不會停止計時器 – Olivier

+1

'setitimer'對於從信號處理程序調用不安全。我想OP只是想關閉計時器。他所需要做的就是在創建計時器時將間隔值清零。 – Duck

+0

@Olihoops我修復了我的答案。正如人們所提到的(並且按照Duck的建議) - 也可以在啓動計時器之前將間隔設置爲零。 – Michael