2012-04-10 3 views
2

코드에서 타이머를 구현하려고합니다. 찾은 모든 예제는 while(1) 또는 for(;;)을 사용하고 있지만 scanf을 사용하려고하면 프로그램이 종료됩니다. stdin에 어떤 값이 있습니까? scanf 두 번 사용하면 타이머가 프로그램에서 나가기 전에 두 번 호출되기 때문입니다.scanf를 사용하는 경우 프로그램 종료

그래서
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <signal.h> 
#include <netinet/in.h> 
#include <signal.h> 
#include <time.h> 

#include <linux/socket.h> 
#include <time.h> 


#define SIGTIMER (SIGRTMAX) 
#define SIG SIGUSR1 
static timer_t  tid; 
static timer_t  tid2; 

void SignalHandler(int, siginfo_t*, void*); 
timer_t SetTimer(int, int); 

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

    int t; 

    printf("SIGRTMAX %d\n", SIGRTMAX); 
     printf("SIGRTMIN %d\n", SIGRTMIN); 

    struct sigaction sigact; 
    sigemptyset(&sigact.sa_mask); 
    sigact.sa_flags = SA_SIGINFO; 
    sigact.sa_sigaction = SignalHandler; 
    // set up sigaction to catch signal 
    if (sigaction(SIGTIMER, &sigact, NULL) == -1) { 
     perror("sigaction failed"); 
     exit(EXIT_FAILURE); 
    } 

    // Establish a handler to catch CTRL+c and use it for exiting. 
    sigaction(SIGINT, &sigact, NULL); 
    tid=SetTimer(SIGTIMER, 1000); 

    struct sigaction sa; 
    sigemptyset(&sa.sa_mask); 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = SignalHandler; 
    // set up sigaction to catch signal 
    if (sigaction(SIG, &sa, NULL) == -1) { 
     perror("sa failed"); 
     exit(EXIT_FAILURE); 
    } 

    // Establish a handler to catch CTRL+c and use it for exiting. 
    sigaction(SIGINT, &sa, NULL); 
    tid2=SetTimer(SIG, 1000); 

    // for(;;); or while(1) Working properly 

    scanf("%d", &t); /// Program terminates 
    return 0; 
} 

void SignalHandler(int signo, siginfo_t* info, void* context) 
{ 


    if (signo == SIGTIMER) { 
     printf("Command Caller has ticked\n"); 

    }else if (signo == SIG) { 
     printf("Data Caller has ticked\n"); 

    } else if (signo == SIGINT) { 
     timer_delete(tid); 
     perror("Crtl+c cached!"); 
     exit(1); // exit if CRTL/C is issued 
    } 
} 
timer_t SetTimer(int signo, int sec) 
{ 
    static struct sigevent sigev; 
    static timer_t tid; 
    static struct itimerspec itval; 
    static struct itimerspec oitval; 

    // Create the POSIX timer to generate signo 
    sigev.sigev_notify = SIGEV_SIGNAL; 
    sigev.sigev_signo = signo; 
    sigev.sigev_value.sival_ptr = &tid; 

    if (timer_create(CLOCK_REALTIME, &sigev, &tid) == 0) 
    { 

     itval.it_value.tv_sec = sec/1000; 
     itval.it_value.tv_nsec = (long)(sec % 1000) * (1000000L); 
     itval.it_interval.tv_sec = itval.it_value.tv_sec; 
     itval.it_interval.tv_nsec = itval.it_value.tv_nsec; 



     if (timer_settime(tid, 0, &itval, &oitval) != 0) 
     { 
      perror("time_settime error!"); 
     } 
    } 
    else 
    { 
     perror("timer_create error!"); 
     return NULL; 
    } 
    return tid; 
} 

, 어떻게이 문제를 해결할 수 있습니다 여기 내 예제 코드인가? 도움을 주시면 감사하겠습니다. 감사합니다, Yuvi

+1

C 또는 C++? (필자가 행복하게 해주는 필러) – pmg

+0

C, @pmg처럼 보입니다. –

+0

신호가 C & C++와 동일하다고 생각합니다. AFAIK – Yuvi

답변

4

신호 인터럽트 scanf. 당신이 후 perror('scanf')를 추가하는 경우는 scanf 출력 될 것입니다 : 그것은 Interrupted system call 실패 할 때

 
do { 
    errno = 0; 
    scanf("%d", &t); 
} while(errno == EINTR); 

는 scanf가 시도됩니다 :

 
SIGRTMAX 64 
SIGRTMIN 34 
Command Caller has ticked 
Data Caller has ticked 
scanf: Interrupted system call 

당신이 scanf를 교체합니다.

2

신호 처리기에서는 printfperror을 사용할 수 없습니다. 그들은 재진입하지 않습니다.

또한 프로그램이 신호를 수신하는 동안 scanf이 오류와 함께 반환 될 수 있습니다. scanf이 EOF를 반환하면 errno을 확인하십시오. 아마 EINTR이됩니다.

+1

이 기능은 기능을 이해하는 샘플 코드 인 async-safe가 아닙니다. – Yuvi