2016-08-24 2 views
0

alarm 함수를 사용하여 getchar을 건너 뛰기 만했으나 한 번 건너 뛸 수 있기 때문에 무언가가 잘 진행되지 않습니다.SIGALRM 알람은 getchar을 한 번만 건너 뜁니다.

예 : 내가 잘못

#include <signal.h> 

int duration = 2; 

main() { 
    cicleProgram(); 
} 

void cicleProgram(){ 

    while(opcion != 'q' && opcion != 'Q'){ 

    signal(SIGALRM, (void*)cicleProgram); 
    alarm(duration); 

    opcion = getchar(); 
    } 
} 

을 뭐하는 거지?

+1

'opcion'의 정의를 게시합니다. – chux

+1

circleProgram을 SIGALRM의 신호 처리기로 설정했습니다. SIGALRM이 발생할 때 운영 체제는 신호 처리기가 반환 할 때까지 프로그램이 SIGALRM을 처리하는 것으로 바쁘다고 가정하므로 다른 신호를 보내지 않습니다. – immibis

+0

또한 신호 처리기에서만 [async-signal-safe] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04) 함수 만 사용할 수 있습니다. Page down - POSIX가 async-signal-safe를 요구하는 함수 목록이 있습니다. 구현시 알람 신호가 보내질 때'getchar()'을 기다려서 다른 프로그램 인'circleprogram()'이 비동기 적으로 시작되도록합니다 - 정상적인 프로그램 흐름 외부. 그것은'getchar()'을 호출하려고 시도하지만 원래 호출은 입력 스트림이 잠겨져있는 상태입니다. –

답변

0

신호 처리기로 cicleProgram()을 사용하고 있습니다. 잘못된 유형 임에도 불구하고 int 인수를 사용해야합니다. 즉, q 또는 Q을 입력 할 때까지 신호 처리기에서 돌아 오지 못하게되며, 첫 번째 신호 처리기가 반환 할 때까지 시스템에서 신호를 차단하고있을 수 있습니다. 따라서 두 번째 신호를 얻지 못합니다. 차단됩니다.

별도의 신호 처리기 기능을 사용하십시오. What is the difference between sigaction() and signal()?을 참조하고 sigaction()signal()보다 우선 사용하십시오.

그리고 적어도 반환 유형은 int main(void)입니다. 심지어 오래된 (C99) 버전의 표준에서도 현재의 (C11) 표준은 말할 것도 없습니다. 우리는 21 세기로 진보했습니다. 20 세기 C에 코드를 작성하지 마십시오!

또한 신호 처리기에서 수행 할 수있는 작업에 대한 정보는 How to avoid using printf() in a signal handler?을 참조하십시오.


나는 몇 가지 컨트롤을 추가 할 수있는 "동안"교착 상태를 신호 알람을 평가하고 피하기 위해?

원본 코드에 여러 가지 문제가 있으며 가능한 모든 문제가 진단되지 않았습니다. 또 하나의 문제는 알람이 울리면 알람을 다시 설정할 것이 없으므로 문자를 입력 할 때까지 프로그램이 대기 상태에 빠지게된다는 것입니다. 두 개의 활성 기능, 각각 루프가 있습니다

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

static int duration = 2; 
static volatile sig_atomic_t alarm_fired = 0; 

static void alarm_handler(int signum) 
{ 
    //signal(SIGALRM, alarm_handler); 
    write(STDOUT_FILENO, "Signalled!\n", 11); 
    alarm_fired = signum; 
    alarm(duration); 
} 

static void cicleProgram(void) 
{ 
    int opcion = 0; 
    while (opcion != 'q' && opcion != 'Q') 
    { 
     signal(SIGALRM, alarm_handler); 
     alarm(duration); 
     if ((opcion = getchar()) == EOF) 
      clearerr(stdin); 
     if (alarm_fired) 
     { 
      alarm_fired = 0; 
      printf("Alarm!\n"); 
     } 
     printf("c = %d\n", opcion); 
    } 
} 

static void actionProgram(void) 
{ 
    struct sigaction sa = { 0 }; 
    sa.sa_handler = alarm_handler; 
    sa.sa_flags = 0; 
    sigfillset(&sa.sa_mask); 
    sigaction(SIGALRM, &sa, 0); 

    int opcion = 0; 
    while (opcion != 'q' && opcion != 'Q') 
    { 
     alarm(duration); 
     if ((opcion = getchar()) == EOF) 
      clearerr(stdin); 
     if (alarm_fired) 
     { 
      alarm_fired = 0; 
      printf("Alarm!\n"); 
     } 
     printf("c = %d\n", opcion); 
    } 
} 

int main(void) 
{ 
    printf("Using signal (q to quit):\n"); 
    cicleProgram(); 
    printf("Using sigaction (q to quit):\n"); 
    actionProgram(); 
    return 0; 
} 

:

다음은 놀이 몇 가지 실험적인 코드입니다. 첫 번째는 원래 cicleProgram()을 기반으로하지만 기능이 개선되었습니다. 더 이상 신호 처리기가 아닙니다. Mac OS X (BSD 기반)에서 실행 중이며이 시스템에서는 신호 처리기 기능에서 signal() 처리기를 재설정 할 필요가 없습니다. 두 번째 함수 인 actionProgram()signal() 대신 sigaction()을 사용합니다. 아마도 필요하지는 않지만 보게 될 것입니다. sa.sa_flags 요소에 SA_RESTART이 없으면 신호가 끊어 질 때마다 시스템 호출이 중단되었다고보고합니다 (read()). signal_handler()의 코드는 허용되지 않는 함수 호출을 사용하지 않습니다.

예 출력 (프로그램 이름 al97) :

$ ./al97 
Using signal (q to quit): 
Signalled! 
Signalled! 
Signalled! 
Signalled! 
WonderfulSignalled! 

Alarm! 
c = 87 
c = 111 
c = 110 
c = 100 
c = 101 
c = 114 
c = 102 
c = 117 
c = 108 
c = 10 
Signalled! 
Signalled! 
q 
Alarm! 
c = 113 
Using sigaction (q to quit): 
c = 10 
Signalled! 
Alarm! 
c = -1 
Signalled! 
Alarm! 
c = -1 
Signalled! 
Alarm! 
c = -1 
Signalled! 
Alarm! 
c = -1 
ASignalled! 
Alarm! 
c = -1 
lso workingSignalled! 
Alarm! 
c = -1 

c = 65 
c = 108 
c = 115 
c = 111 
c = 32 
c = 119 
c = 111 
c = 114 
c = 107 
c = 105 
c = 110 
c = 103 
c = 10 
qSignalled! 
Alarm! 
c = -1 

c = 113 
$ 

는 실행에 약간의 꽤 긴 일시 정지가 있었다, 그러나 당신은 당신의 컴퓨터에 실험 할 수있다. cicleProgram()에 대해 alarm_handler() 함수의 signal()을 다시 포함하고 actionProgram()에 대해 다른 핸들러를 사용해야합니다 (지금은 signal()을 사용하지 않음).

+0

그래서 신호 알람을 평가하고 교착 상태를 피하기 위해 "while"에서 일부 컨트롤을 추가 할 수 있습니까? 감사합니다. – DAM

+0

@DAM : 업데이트 된 답변보기 - 놀고, 즐겨라. –

+0

고마워요! 내가 그 코드를 증명하면 더 가까이에서 일어나는 일을 볼 수 있습니다. 정말 고마워요 – DAM

관련 문제