6. sigaction() 함수에 대한 고찰

System Program/signal 2013. 7. 8. 13:07

1. sigaction()함수란?

 

signal()함수와 같이 시그널 속성을 설정하는 함수이다.

sigaction()은 시그널 핸들러를 만들 때, signal()보다는 복잡하지만 이식성이 좋은 장점이 있다.   

 

#include <signal.h>

 


int sigaction(int signum,  const  struct  sigaction  *act, struct sigaction *oldact);

 

                                                                                            성공하면 '0', 에러가 발생하면 '-1'을 리턴한다.  

 

2. sigaction 구조체

 

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_flag에 대해서 자세히 알아본다. sa_flag는 시그널이 어떻게 처리돼야 하는지를 제어한다.

여러 옵션은 아래와 같으며 OR 연산으로 같이 쓸 수 있다.

 

  • SA_NOCLDSTOP

      - sig가 SIGCHLD인 경우, 시그널을 추출한 결과로 자식프로세스가 멈추거나 재개될 때,

         이 시그널을 생성하지 않는다.

  • SA_NOCLDWAIT

      - sig가 SIGCHLD인 경우에, 자식들이 제거될 때 좀비로 변하지 않는다.

  • SA_NODEFER

      - 이 시그널이 잡히면, 핸들러가 실행 중일때 프로세스 시그널 마스크에 자동적으로 추가하지 않는다.

  • SA_ONSTACK

      - sigaltstack()에 설치된 대체 스택을 사용해 이 시그널에 대한 핸들러를 실행한다.

  • SA_RESEHAND

      - 이 시그널이 잡히면, 핸들러를 실행하기 전에 기본 속성(SIG_DLF)으로 변경한다.

  • SA_RESTART

      - 시그널 핸들러에 의해 중지된 시스템 호출을 자동적으로 재시작한다.

  • SA_SIGINFO

      - 시그널에 대한 더 많은 정보를 제공하는 추가적인 인자로 시그널 핸들러를 실행한다.

 

3. 예제

 

/*
* main.c -- C Test App.
*
* Copyright (C) 2012-2013, 2013 heesoon.kim <chipmaker.tistory.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#define MAX_SLEEP_TIME 2

static int sigCnt[NSIG];
static volatile sig_atomic_t gotSigint = 0;

void printSigSet(FILE *of, const char *prefix, const sigset_t *sigset)
{
	int sig, cnt;
	
	cnt = 0;
	
	for(sig = 1; sig < NSIG /*32*/; sig++)
	{
		if(sigismember(sigset, sig))
		{
			cnt++;
			
			fprintf(of, "%s%d (%s)\n", prefix, sig, strsignal(sig));
		}
	}
	
	if(cnt == 0)
		fprintf(of, "%s<empty signal set >\n", prefix);
}

void signal_handler(int sig)
{
	sigset_t pendingMask;

	if(sig == SIGINT)
		gotSigint = 1;
	else
	{
		sigCnt[sig]++;
		
		if(sigpending(&pendingMask) == -1)
			fprintf(stderr, "sigpending\n");
	
		printSigSet(stdout, "\t\t",  &pendingMask);			
		
		sleep(MAX_SLEEP_TIME);
	}
}

int main(int argc, char *argv[])
{
	int i;
	struct sigaction sigact;
	//sigset_t pendingMask;
		
	printf("%s: PID is %ld\n", argv[0], (long)getpid());
		
	sigact.sa_handler = signal_handler;
	sigfillset(&sigact.sa_mask);	
	//sigact.sa_flags = SA_RESETHAND | SA_RESTART;
	sigact.sa_flags = SA_RESTART;
	
	sigaction(SIGUSR2, &sigact, NULL);
	sigaction(SIGINT, &sigact, NULL);
		
	while(!gotSigint)
		continue;
	
	for(i = 1; i < NSIG; i++)
	{
		if(sigCnt[i] != 0)
			printf("%s: signal %d caught %d time%s \n", argv[0], i, sigCnt[i], (sigCnt[i] == 1) ? "" : "s");
	}
	
	exit(EXIT_SUCCESS);
	
	return 0;
}


 

4. 설명

 

앞 장에서 시그널을 전송하고 수신하는 예제에서 수신하는 프로그램을 수정하였다.

기존 앞 장은 signal()함수를 사용하였으나 여기서는 sigaction()함수로 대체하였다.

 

기존 앞 장에서는 signal()함수를 쓸 때는 여러가지 추가적인 시그널 처리 함수들을 호출하였다.

하지만 sigaction()함수는 그런 추가적인 함수 호출없이 동일한 기능을 할 수 있다.

 

 

 

'System Program > signal' 카테고리의 다른 글

1. 개념과 개요  (0) 2014.02.19
5. (1 ~ 4)장에 대한 총괄 예제  (0) 2013.07.08
3. 시그널 전송 방법(시스템 콜)  (0) 2013.07.08
2. 시그널의 종류와 사용법  (0) 2013.07.08
: