2009-11-23 4 views
24
#include <stdio.h> 
#include <signal.h> 


void ALARMhandler(int sig) 
{ 
    signal(SIGALRM, SIG_IGN);   /* ignore this signal  */ 
    printf("Hello"); 
    signal(SIGALRM, ALARMhandler);  /* reinstall the handler */ 
} 

int main(int argc, char *argv[]) 
{ 
    alarm(2);      /* set alarm clock   */ 
    while (1) 
    ; 
    printf("All done"); 
} 

나는 프로그램 2 초 후 "안녕하세요"인쇄 할 것으로 예상, 대신 출력은 다음과 같습니다간단한 신호 - C 프로그래밍 및 알람 기능은

어떤 생각이 무엇인가 "zsh을 ./a.out 경보" 계속 하시겠습니까?

답변

31

처음에는 알람 처리기를 설정하는 것을 잊어 버리는 것입니다. main()의 시작을 변경 좋아 :

int main(int argc, char *argv[]) 
{ 
    signal(SIGALRM, ALARMhandler); 
    ... 

는 또한, 신호 처리기는 아마 아무것도 인쇄하지 않습니다. 왜냐하면 C 라이브러리는 라인의 끝이 보일 때까지 출력을 캐시하기 때문입니다. 따라서 :

void ALARMhandler(int sig) 
{ 
    signal(SIGALRM, SIG_IGN);   /* ignore this signal  */ 
    printf("Hello\n"); 
    signal(SIGALRM, ALARMhandler);  /* reinstall the handler */ 
} 

실제 프로그램의 경우 신호 처리기에서 인쇄하는 것은 그리 안전하지 않습니다. 신호 처리기는 가능한 한 적은 작업을 수행해야하며, 여기 또는 여기에 플래그를 설정하는 것이 바람직합니다. 그리고 깃발은 volatile이라고 선언해야합니다.

+22

그러나 실 나는 버전 1 인쇄 (매초)이 테스트 월드의 예 : Access 데이터베이스를 백엔드로 사용하는 시스템에서 한 번 작업 한 적이 있는데 특정 상황에서 신호 처리기의'printf()'호출이 stdout 대신 .mdb 파일에 기록하여 복구 할 수 없을 정도로 데이터베이스를 덮었습니다 . –

5

먼저 신호 처리기를 설치하지 않습니다.
실제로 신호를 받기 전에 신호를 처리 할 것을 시스템에 알려야하므로 신호가 오기 전에 signal()을 main에서 호출해야합니다.

int main(int argc, char *argv[]) 
{ 
    signal(SIGALRM, ALARMhandler);  /* install the handler */ 
    alarm(2);      /* set alarm clock   */ 
    while (1); 
} 
9

main 함수에서 처리기를 설정하지 않습니다.

alarm(2)하기 전에 mainsignal(SIGALRM, ALARMhandler);을 넣으십시오.

그러면 작동합니다.

신호 처리기를 실행 한 후에 while (1) 루프 상태를 유지하므로 "모두 완료"가 인쇄되지 않습니다. 루프가 깨지지 않게하려면 신호 처리기가 변경하는 플래그가 있어야합니다.

#include <stdio.h> 
#include <signal.h> 

/* number of times the handle will run: */ 
volatile int breakflag = 3; 

void handle(int sig) { 
    printf("Hello\n"); 
    --breakflag; 
    alarm(1); 
} 

int main() { 
    signal(SIGALRM, handle); 
    alarm(1); 
    while(breakflag) { sleep(1); } 
    printf("done\n"); 
    return 0; 
} 
+4

+1 멋진 프로그램. 나는 당신이 시그널 핸들러에서'alarm (2)'를 호출해야한다고 생각한다 : 보통 하나의'alarm()'호출은 오직 하나의'SIGALRM' 만 생성한다. – Andomar

+0

물론, 당신 말이 맞다. 분명히이 코드를 테스트하지 않았고 잠시 동안 이런 방식으로 신호를 사용하지 않았습니다 (특히이 방법을 사용하는 스레드 환경에서는 쓸모가 없습니다). – McPherrinM

+0

breakflag 변수에 휘발성 저장소 클래스를 지정해야하는 이유는 무엇입니까? – sujin

4

Andomar는 rigth입니다.

Hi... 
Hi... 
Hi... 
Hi... 
BYE 
Hi... 
... 

버전이 인쇄 (5 초마다) :

Hi...Hi...Hi...Hi...BYE 
Hi...Hi...Hi...Hi...BYE 
... 

그래서 코드는 다음과 같습니다

#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 

# define T 5 

int flag = T; 

void sigalrm_handler(int); 

int main(void) 
{ 
    signal(SIGALRM, sigalrm_handler); 
    alarm(1);       
    while (1); 
} 

void sigalrm_handler(int sig) 
{ 
    if(--flag){ 
     printf("Hi...\n"); /*version 1*/ 
     /*printf("Hi...");*/ /*version 2*/ 
    }else{ 
     printf("BYE\n"); 
     flag=T;  
    } 
    alarm(1); 
} 
+0

완전하고 작동하는 코드를 보내 주셔서 감사합니다. 방금 기존 프로그램의 메인 {}의 상단에 붙여 넣은 다음 해고했습니다. – user2548100

관련 문제