시그널이 처리하는 동작은 3개이다.
주요 시그널 번호는 다음과 같다.
sighandler_t signal(int signum, sighandler_t handler);
파라미터
- signum: 처리 대상 시그널 번호
- handler: 시그널 핸들러
- SIG_IGN: 해당 시그널을 무시 처리 한다.
- SIG_DFL: 해당 시그널을 기본 동작 처리 한다.
- 그외 사용자 정의 시그널 핸들러
반환값
- 성공 : 이전 시그널 핸들러
- 실패 : SIG_ERR
int kill(pid_t pid, int sig);
파라미터
- pid: 시그널 송신 대상 지정
- 1 이상: 프로세스 ID
- 0: 프로세스 그룹 전체
- -1: 권한 내의 모든 프로세스
- -1 미만: 프로세스 그룹 아이디가 (-pid)인 프로세스 그룹 전체
- sig: 보낼 시그널 번호
- 단, 0인 경우 보내지는 않고, process 유무 및 권한 판단 수행
반환값
- 하나 이상의 프로세스에게 송신시: 0
- 실패: -1
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
파라미터
- how
- SIG_BLOCK: blocked signal에 추가
- SIG_UNBLOCK: 현재 blocked signal에서 제외
- SIG_SETMASK: set 변수를 blocked signal로 설정
- set: 설정할 sigset
- oldset: 기존 설정되어 있던 sigset
반환값
- 성공: 0
- 실패: -1
int sigemptyset(sigset_t *set);
- sigset 변수를 empty set으로 설정(아무런 시그널 설정되어 있지 않음)
int sigfillset(sigset_t *set);
- sigset 변수에 모든 시그널을 설정
int sigaddset(sigset_t *set, int signum);
- sigset 변수에 특정 시그널을 추가
int sigdelset(sigset_t *set, int signum);
- sigset 변수에서 특정 시그널을 삭제
int sigismember(const sigset_t *set, int signum); - sigset 변수에서 특정 시그널이 포함되어 있는지 확인
- 포함시1리턴
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
파라미터
- signum: 대상 시그널 번호
- act: 시그널 처리 액션
- oldact: 기존 시그널 처리 액션
반환값
- 성공: 0
- 실패: -1
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); /* 사용되지 않음 */
};
flags | 의미 |
---|---|
SA_SIGINFO | sa_sigaction()이 사용됨. |
SA_NODEFER | 설정시 시그널 핸들러가 실행 중인 시그널에 대해 블록하지 않음 |
SA_NOCLDSTOP | signo가 SIGCHLD인 경우 자식이 정지해도 SIGCHLD를 보내지 않도록 함 |
SA_NOCLDWAIT | signo가 SIGCHLD인 경우 자식에 대한 자동처리 활성화 (wait() 필요 없음) |
SA_RESETHAND | 시그널 핸들러가 1회면 동작한 후 default로 초기화 된다. |
SA_RESTART | read()등의 시스템콜이 자동으로 재시작된다. |
siginfo_t {
int si_signo; /* Signal number (주요)*/
int si_errno; /* An errno value (주요) */
int si_code; /* Signal code (주요) */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal sigqueue()를 통해 보낸 시그널 페이로드 */
void *si_ptr; /* POSIX.1b signal sigqueue()를 통해 보낸 시그널 페이로드 */
int si_overrun; /* Timer overrun count;
POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault
SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP의 경우 장애를 일으킨 주소*/
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor SIGPOLL의 경우 작업을 완료한 파일 디스크립터 */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
void *si_lower; /* Lower bound when address violation
occurred (since Linux 3.19) */
void *si_upper; /* Upper bound when address violation
occurred (since Linux 3.19) */
int si_pkey; /* Protection key on PTE that caused
fault (since Linux 4.6) */
void *si_call_addr; /* Address of system call instruction
(since Linux 3.5) */
int si_syscall; /* Number of attempted system call
(since Linux 3.5) */
unsigned int si_arch; /* Architecture of attempted system call
(since Linux 3.5) */
}
si_code | meaning |
---|---|
SI_ASYNCIO | 비동기식 입출력의 완료 표시 |
SI_KERNEL | 커널이 보낸 시그널 |
SI_MESGQ | POSIX 메시지 큐의 상태 변화 표시 |
SI_QUEUE | sigqueue()로 보낸 시그널 |
SI_TIMER | POSIX 타이머 만료를 표시 |
SI_USER | kill() 또는 raise()로 보낸 시그널 |
si_code | meaning |
---|---|
CLD_CONTINUED | 자식이 정지되었다가 재시작됨 |
CLD_DUMPED | 자식이 비정상적으로 종료됨 |
CLD_EXITED | 자식이 exit()로 정상 종료됨 |
CLD_KILLED | 자식이 종료됨 |
CLD_STOPPED | 자식이 정지됨 |
CLD_TRAPPED | 자식이 트랩에 걸림 |
union sigval {
int sival_int;
void *sival_ptr;
};
int sigqueue(pid_t pid, int signo, const union sigval value);
파라미터
- pid: 대상 프로세스
- signo: 시그널 번호
- value: 페이로드
반환값
- 성공: 0
- 실패: -1
해당 시그널을 sigaction()으로 받으면...#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/signal.h>
void ctrl_c_sighandler(int signum)
{
printf("CTRL + C \n");
}
int main(int argc, char **argv)
{
signal(SIGINT, ctrl_c_sighandler);
while(1){
sleep(1);
}
return 0;
}