Linux/Linux_programing

IPC - 02. 신호 처리, sigaction 안정적 신호 인터페이스

sosal 2009. 10. 31. 07:37
반응형

/*
 http://sosal.tistory.com/
 * made by so_Sal
 */



01.에서 봤던 kill 명령어를 더 자세히 보겠습니다.

#include<sys/types.h>
#include<signal.h>

int kill(pid_t pid, int sig);

인자만 봐도 쉽게 알 수 있듯, kill 명령어에는 해당되는 프로세스 id와 명시적 sig를 전달합니다.


#include<unistd.h>
int pause(void);
신호가 발생할 때까지 프로그램의 실행을 정지합니다.
신호를 받으면 호출되는 신호 처리부의 행동을 재개합니다.

* 안정적 신호 인터페이스 sigaction

#include<signal.h>
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
    **** struct sigaction 구조체가 중요 ****
첫번째 인자 sig로 지정된 신호를 받았을 때, ssigaction 구조체가 수행할 행동을 정의한다.

struct sigaction
{
    void (*sa_handler)(int);
    sigset_t sa_mask;
    void (*sa_sigaction)(int, siginfo_t *, void *);
    int sa_flags;
    void (*sa_restorer)(void);
}

sa_handler : signal에 따른 실행된 함수 설치와 SIG_DFL, SIG_IGN 지정 가능
(SIG_DFL :: 기본행동 지속, SIG_IGN :: 신호 무시 ignore)
sa_mask :: sa_handler에서 함수가 실행되는 동안 차단할 신호
sa_flags :: 신호 처리 프로세스의 행위 수정하는 flags

sa_falgs의 플레그들
*** sa_flags에 대한 내용은 유명한 yundream 블로그에 너무 정리가 잘 되어있어서 퍼왔습니다. ***
http://disqus.com/yundream/


sa_flags

시그널 처리 프로세스의 행위를 수정하는 일련의 플래그들을 명시한다.
  다음중 하나 이상의 것들에 의해서 만들어 진다.
 
SA_NOCLDSTOP
만약 signum이 SIGCHLD라면, 자식 프로세스가 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU등을 받아서 중단되었을   때 이를 통지 받을 수 없게 된다.

SA_ONESHOT, SA_RESETHAND
일단 시그널 처리기가 호출되면, 기본 상태에 대한 시그널 액션을 재 저장한다.

이는 signal(2)호출에 대한 기본 행위이다.

SA_RESTART
일부 시스템 호출들이 시그널을 통해 재시작할 수 있도록 함으로서 BSD 시그널과 호환되도록 한다.
 
SA_NOMASK, SA_NODEFER
시그널이 자체 시그널 처리기로부터 수신 받지 않도록 한다.

SA_SIGINFO
시그널 처리기가 하나가 아닌 3개의 인자를 취할경우 sa_handler대신
   sigaction의 siginfo_t를 이용할 수 있다. siginto_t는 다음과 같이 정의된 구조체이다.
 
siginfo_t {
    int      si_signo;  /* 시그널 넘버 */
    int      si_errno;  /* errno 값 */
    int      si_code;   /* 시그널 코드 */
    pid_t    si_pid;    /* 프로세스 ID 보내기 */
    uid_t    si_uid;    /* 프로세스를 전송하는 실제 사용자 ID */
    int      si_status; /* Exit 값 또는 시그널 */
    clock_t  si_utime;  /* 소모된 사용자 시간 */
    clock_t  si_stime;  /* 소모된 시스템 시간 */
    sigval_t si_value;  /* 시그널 값 */
    int      si_int;    /* POSIX.1b 시그널 */
    void *   si_ptr;    /* POSIX.1b 시그널 */
    void *   si_addr;   /* 실패를 초래한 메모리 위치 */
    int      si_band;   /* 밴드 이벤트 */
    int      si_fd;     /* 파일 기술자 */
}

SIGCHLD 시그널은 si_pid, si_uid, si_status, si_utime, si_stime를 채운다. si_int, si_ptr은 시그널의 송신자에 의해서 명시될 수 있다.

si_code는 왜 시그널이 보내졌는지를 지시한다. 

** yundream 님의 블로그의 일부 내용이었습니다. **

예제 소스.

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void _signal(int sig){
    printf("I got signal! \n");
}
int main(void){
    int i;
    struct sigaction action; //sigaction 구조체 선언
    action.sa_handler = _signal;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGINT, &action, 0);
    while(1){
        printf("hi\n");
        sleep(1);
    }
}
begining Linux programing 예제 부분을 조금 참조하였습니다.