Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
Docbook 원문

sigaction(2)

1장. sigaction(2)

차례
1.1. 사용법
1.2. 설명
1.3. 반환값
1.4. 에러
1.5. 예제
1.6. 참고문헌

시그널 처리관련 함수


1.1. 사용법

#include <signal.h>
int sigaction(int signum,  const  struct  sigaction  *act,
	struct sigaction *oldact);
int  sigprocmask(int  how,  const  sigset_t *set, sigset_t *oldset);
int sigpending(sigset_t *set);
int sigsuspend(const sigset_t *mask);
		


1.2. 설명

sigaction() 시스템 호출은 특정 시그널(:12)의 수신에 대해서 취할 액션을 설정하거나 변경하기 위해서 사용된다.

signum는 시그널을 명시한다. SIGKILL(:12)과 SIGSTOP(:12)를 제외한 모든 시그널이 타당한 시그널이 될 수 있다.

만약 actnull이 아니라면 signum번호를 가지는 시그널에 대해서 act함수가 설치된다. 만약 oldact가 null이 아니라면 이전의 액션은 oldact에 저장된다.

sigaction구조체는 다음과 같이 정의되어 있다.

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

sa_handler

signum번호를 가지는 시그널이 발생했을 때 실행된 함수를 설치한다. 함수외에도 SIG_DFL과 SIG_IGN을 지정할 수 있다. 전자는 시그널에 대한 기본행동을 후자는 시그널을 무시하기 위해서 사용한다.

sa_mask

sa_handler에 등록된 시그널 핸들러 함수가 실행되는 동안 블럭되어야 하는 시그널의 마스크를 제공한다. SA_NOMASK가 적용되어 있지 않다면

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는 왜 시그널이 보내졌는지를 지시한다.

sigprocmask()는 현재 블록된 시그널들을 변경시키기 위해서 사용한다. 호출의 행위는 how 값들에 대해서 의존적이 된다. how는 다음중 하나를 선택할 수 있다.

SIG_BLOCK

set에 설정된 시그널을 블럭 시그널셋에 추가시킨다.

SIG_UNBLOCK

시그널 셋set의 시그널을 현재의 블럭된 시그널에서 삭제한다.

SIG_SETMASK

시그널 셋set의 시그널을 블럭화된 시그널로 지정한다.

oldset이 null이 아니면, 시그널:::마스크(:12)의 이전 값은 oldset에 저장된다.

sigpending()함수는 전달 시그널들에 대한 검사를 허용한다. 전달 시그널들의 마스크는 set에 저장된다.

sigsuspend()는 프로세스의 시그널 마스크를 일시적으로 mask로 대체하고, 시그널이 수신될때까지 프로세스를 중지시킨다.


1.3. 반환값

성공하면 0을 실패하면 -1을 리턴한다.


1.4. 에러

EINVAL

부적절한 시그널이 지정되거나. 무시할 수 없는 SIGKILL SIGSTOP에 대한 액션을 변경하고자 할 경우

EFAULT

act, oldact, set, oldset 이 타당하지 않은 메모리 영역을 가리킬 경우

EINTR

시스템 호출이 인터럽트(:12) 되었다.


1.5. 예제

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

void sig_int(int signo);
void sig_usr(int signo);

int main()
{
    int i = 0;
    struct sigaction intsig, usrsig;

    usrsig.sa_handler = sig_usr;
    sigemptyset(&usrsig.sa_mask);
    usrsig.sa_flags = 0;

    intsig.sa_handler = sig_int;
    sigemptyset(&intsig.sa_mask);
    intsig.sa_flags = 0;

	// SIGINT에 대해서 sig_int를 등록한다. 
    if (sigaction(SIGINT, &intsig, 0) == -1)
    {
        printf ("signal(SIGINT) error");
        return -1;
    }    

	// SIGUSR2에 대해서 usrsig를 등록한다. 
    if (sigaction(SIGUSR2, &usrsig, 0) == -1)
    {
        printf ("signal(SIGUSR2) error");
        return -1;
    }    

    while(1)
    {
        printf("%d\n", i);
        i++;
        sleep(1);
    }
}

void sig_int(int signo)
{
    sigset_t sigset, oldset;

	// 핸들러가 수행되는 동안 수신되는 모든 시그널에 대해서
	// 블럭한다.  
    sigfillset(&sigset);
    if (sigprocmask(SIG_BLOCK, &sigset, &oldset) < 0)
    {
        printf("sigprocmask %d error \n", signo);
    }
    fprintf(stderr, "SIGINT !!!!\n");
    sleep(5);
}

void sig_usr(int signo)
{
    printf("sig_usr2\n");
}