프로그래밍/리눅스
리눅스 시그널 (signal)
꿀두유
2014. 10. 2. 17:18
리눅스에서 단 한번이라도 프로그래밍을 해봤다면 control+c를 누르면 프로그램이 중지되는 걸 볼 수 있을 것이다.
이건 현재 실행중인 프로그램을 중지할 수 있는 무언가(?)를 했기 때문이다.
이런 무언가를 리눅스에서는 시그널(Signal)이라고 한다.
시그널의 종류는 굉장히 많은데 signum.h에 가보면 그 종류를 볼 수 있다.
리눅스에서 프로그램이 실행하는 중에는 다양한 상황에 따라 OS에서 프로그램에 시그널을 날릴 수 있는데,
이러한 시그널을 캐치해서 내가 의도하는 대로 프로그램을 돌아갈 수 있도록 만들어야 대처할 수 있으며 편해진다.
이에 필요한 정보를 이제부터 하나하나 봐야겠다.
/* Structure describing the action to be taken when a signal arrives. */ struct sigaction { /* Signal handler. */ #ifdef __USE_POSIX199309 union { /* Used if SA_SIGINFO is not set. */ __sighandler_t sa_handler; /* Used if SA_SIGINFO is set. */ void (*sa_sigaction) (int, siginfo_t *, void *); } __sigaction_handler; # define sa_handler __sigaction_handler.sa_handler # define sa_sigaction __sigaction_handler.sa_sigaction #else __sighandler_t sa_handler; #endif /* Additional set of signals to be blocked. */ __sigset_t sa_mask; /* Special flags. */ int sa_flags; /* Restore handler. */ void (*sa_restorer) (void); };
sa_handler : 시그널 핸들러. SIG_DFL 이 기본 값인데 시그널 자체의 행동을 수행한다. SIG_IGN을 넣어주면 해당 시그널을 무시한다.
하지만 가장 중요한 것! 만약 여기에 시그널 핸들러의 포인터/함수이름을 주게 되면 그에 정의된 행동을 수행하게 된다.
sa_mask : 마스크값으로 시그널 핸들러가 수행되는 동안 시그널을 block 혹은 non-block 으로 만드는 요소다.
일반적으로 시그널은 쌓이지 않는데, sa_mask는 시그널이 처리되는 동안 나머지 시그널들을 블로킹 상태에 있도록 해서 순차적으로 시그널을 발생시키는 역할을 하게 된다.
sa_flags : 시그널의 특성을 결정하는 변수로 or연산자(|)를 이용해서 여러개의 값을 줄 수 있다. 기본적으로 0을 준다.
SA_NOCLDSTOP : 자식 프로세스가 중단 되었을 때 SIGCHLD 값을 받지 않는다.
SA_ONESHOT : 한번 해당 시그널이 처리된 후에 signal action의 기본값을 재저장한다.
SA_RESTART : SA_ONESHOT 과 반대되는 개념으로, signal action의 값을 저장하지 않는다. BSD 시그널에만 적용.
SA_NOMASK : 시그널 핸들러로부터 발생되는 자체 시그널을 받지 않도록 한다.
예제
예제
#include#include #include #include void Handler(int signo) { printf("Catch handler no : %d\n", signo); switch (signo) { case SIGINT: printf("catch SIGINT\n"); break; case SIGALRM: printf("catch SIGALRM\n"); break; } // end of switch exit(0); } void CreateSignal() { struct sigaction action; action.sa_handler = Handler; sigfillset(&action.sa_mask); action.sa_flags = 0; sigaction(SIGINT, &action, NULL); sigaction(SIGALRM, &action, NULL); } int main() { CreateSignal(); alarm(6); while (true) { printf("Continue..\n"); sleep(1); } // end of while }
만약 위 프로그램이 실행되는 동안 control+c를 입력하면 "catch SIGINT"가 출력된다.