2011-11-26 183 views
0

剛剛瞭解到sigacation,還實現了另一個計時器以使其更有趣。scanf循環和信號處理程序

#include <stdio.h> 
#include <signal.h> 
#include <sys/time.h> 

volatile sig_atomic_t gotsignal; 


void handler(){ 

    gotsignal = 1; 

} 

int main(){ 

struct sigaction sig; 
struct itimerval timer; 

timer.it_value.tv_sec = 5; 
timer.it_value.tv_usec = 0; 
timer.it_interval = timer.it_value; 

sig.sa_handler = handler; 
sig.sa_flags = 0; 
sigemptyset(&sig.sa_mask); 

setitimer(ITIMER_REAL, &timer, 0); 
sigaction(SIGALRM, &sig, NULL); 


int value, y = 100, x=0; 

while(!gotsignal && x < y){ 
    printf("Insert a value: \n"); 
    scanf("%d", &value); 
    x+=value; 
    printf("Current x value: %d\n", x); 
} 
} 

我不明白的是,當它等待用戶輸入,我寫5,但沒有按回車。他仍然讀它?他不應該清除它嗎? 輸出它給我:

Insert a value: 
1 
Current x value: 1 
Insert a value: 
2 
Current x value: 3 
Insert a value: 
5Current x value: 5 

我想會是這樣:

Insert a value: 
1 
Current x value: 1 
Insert a value: 
2 
Current x value: 3 
Insert a value: 
5(Wthout pressing enter!)Current x value: 3 (He would forget about 5 no?) 

回答

3

A(迂腐)正確signal處理程序可以做的非常幾件事情:特別設置volatile sig_atomic_t變量(這是一些整數類型),也許呼籲siglongjmp [我甚至不知道siglongjmp]。

所以先申報

volatile sig_atomic_t gotsignal; 

那麼你的信號處理僅僅是

void handler (void) 
{ 
    gotsignal = 1; 
} 

和你的循環是

while(!gotsignal && x < y){ 
    printf("Insert a value: \n"); 
    scanf("%d", &value); 
    x+=value; 
} 

不要忘了異步信號發生在任何時間(任何ma chine指令!!!),其中包括mallocprintf。切勿從處理程序中調用這些函數。

與信號處理不良相關的錯誤很難調試:它們是不可重現

考慮使用sigaction

+0

嗯。這就說得通了。但是如果我希望程序在信號之後停止等待scanf。例如,一旦他獲得信號,他就會忘記他正在等待的scanf並正常重啓循環。那可能嗎? – JPS

+0

我認爲'SIGALRM'信號將會停止'scanf',因爲'read'系統調用(由'scanf'調用)會得到'EINTR'錯誤。您可能還想了解關於「select」,「pselect」或「poll」(或「ppoll」)系統調用的信息。您可以測試'scanf'是否因其返回值失敗。 –

+0

+1也用於提示'sigaction',它與'signal'不同,完全符合POSIX。 – jweyrich