6. sigaction() 함수에 대한 고찰
System Program/signal 2013. 7. 8. 13:071. sigaction()함수란?
signal()함수와 같이 시그널 속성을 설정하는 함수이다.
sigaction()은 시그널 핸들러를 만들 때, signal()보다는 복잡하지만 이식성이 좋은 장점이 있다.
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
성공하면 '0', 에러가 발생하면 '-1'을 리턴한다.
2. sigaction 구조체
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 |