Untitled

sigaction 은 signal 함수보다는 조금 더 다양한 기능을 지원하는 시그널 함수이다.

sigaction 함수는 <sys/signal.h>에 정의된 sigaction 구조체를 활용하며, sigaction 구조체가 지원하는 다양한 기능을 사용할 수 있다.

sigaction 함수

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
// 성공시 0, 실패시 -1 할당

특정 시그널 넘버에 대해 작동할 sigaction 구조체를 지정한다.

sigaction 구조체

struct sigaction {
    void (*sa_handler)(int);    // signal 핸들러 함수
    void (*sa_sigaction)(int, siginfo_t *, void *);
    // 밑의 sa_flags가 SA_SIGINFO일때 sa_handler 대신에 동작하는 핸들러
    sigset_t sa_mask;             // 시그널 처리시 블록 지정할 시그널 마스크
    int sa_flags;                // sig_flag 기능 지정을 위한 상수
    void (*sa_restorer)(void);  // 응용프로그램 코드에서는 사용하지 말자.
}

sigaction 함수를 사용하기 위해서는 sigaction 구조체를 프로그램 코드 내부에 선언해야 한다. signal 함수는 핸들러 함수를 등록하기 위해 사용하지만, sigaction 함수는 sigaction 구조체를 선언하고 내부에 핸들러를 등록한 뒤 그 구조체를 사용하기 때문이다.

void ft_signal_handler(...)
{
    ...
}

...
struct sigaction sig_strct;
...

sig_strct.sa_handler = ft_signal_handler;
sigaction(SIGUSR1, sig_strct, NULL);

위와 같이 sigaction 함수로 시그널과 sigaction 구조체를 등록한다.

sa_handler, sa_sigaction 등록

두 멤버는 메모리 영역 단위로 보았을 때 중첩된다. 즉, 두 멤버 모두 시그널이 들어왔을 때에 어떤 동작을 할 지 핸들러 함수를 지정할 때에 사용한다.

두 멤버의 차이는 아래의 sa_flag에서 SIGINFO의 사용 여부에 따른다. SIGINFO를 사용하지 않을 경우, sa_handler에 시그널 핸들러 함수를 할당한다. 그렇지 않고 SIGINFO를 사용하는 경우라면 sa_sigaction에 시그널 핸들러 함수를 할당한다.

// error
sig_strct.sa_handler = ft_signal_handler;
sig_strct.sa_flag = SA_SIGINFO;
sigaction(SIGUSR1, sig_str, NULL);

// correct
sig_strct.sa_sigaction = ft_signal_handler;
sig_strct.sa_flag = SA_SIGINFO;
sigaction(SIGUSR1, sig_str, NULL);

sa_flag

signal 함수와 sigaction 사이에 가장 큰 차이점은 sa_flag를 이용한 다양한 기능의 지원을 꼽을 수 있다. 아래의 플래그를 이용하여, 해당 sigaction 구조체의 핸들러가 발동될 때에 다양한 옵션들을 사용할 수 있도록 한다.

sa_flag 에서는 or 연산자(||)를 활용하여 여러가지 플래그 값을 넣어줄 수 있다.

플래그 설명
SA_NOCLDSTOP 이 값이 설정되어 있고 시그널이 SIGCHLD면 자식 프로세스가 중지 또는 재시작할 때 부모 프로세스에 SIGCHLD 시그널을 전달하지 않는다.
SA_ONESHOT 이 값을 설정하고 시그널을 받으면 시그널의 기본 처리 방법은 SIG_DFL로 재설정되고 시그널이 처리되는 동안 시그널을 블록하지 않는다.
SA_RESETHAND 이 값을 설정하고 시그널을 받으면 시그널의 기본 처리 방법은 SIG_DFL로 재설정되고 시그널이 처리되는 동안 시그널을 블록하지 않는다.(SA_ONESHOT 이랑 동일)
SA_NOCLDWAIT 이 값을 설정하고 시그널 SIGCHLD을 처리하는 경우, 시스템은 자식 프로세스가 종료될 때 좀비 프로세스를 만들지 않는다.
SA_ONSTACK 이 값을 설정하고 시그널을 받으면, sigaltstack 함수를 호출하여 대체 시그널 스택이 있을 시 대체 스텍에서 처리하게 한다.
SA_RESTART 이 값을 설정하고 시그널을 받으면 시스템은 시그널 핸들러에 의해 중지된 기능을 재시작하게 한다.
SA_NOMASK 이 값을 설정하고 시그널을 받으면 시그널이 처리되는 동안 전달되는 시그널은 자동으로 블록되지 않는다.
SA_NODEFER 이 값을 설정하고 시그널을 받으면 시그널이 처리되는 동안 전달되는 시그널은 자동으로 블록되지 않는다.(SA_NOMASK 와 동일)
SA_SIGINFO 이 옵션이 사용되면 sa_handler대신에 sa_sigaction이 동작되며, sa_handler 보다 더 다양한 인수를 받을 수 있다. sa_sigaction이 받는 인수에는 시그널 번호, 시그널이 만들어진 이유, 시그널을 받는 프로세스의 정보가 있다.

siginfo 구조체