# signal
시그널 처리하는 방법을 설정하는 함수
void (*signal(int signum, void (*handler)(int)))(int);
이전에 설정된 시그널 핸들러를 반환한다. : void *()(int)
- int signum : 시그널 넘버
- void (*handler)(int) : 시그널을 처리할 핸들러
+ 시그널의 종류
1) SIGHUP | 2) SIGINT | 3) SIGQUIT | 4) SIGILL | 5) SIGTRAP | 6) SIGABRT | 7) SIGBUS | 8) SIGFPE |
9) SIGKILL | 10) SIGUSR1 | 11) SIGSEGV | 12) SIGUSR2 | 13) SIGPIPE | 14) SIGALRM | 15) SIGTERM | 17) SIGCHLD |
18) SIGCONT | 19) SIGSTOP | 20) SIGTSTP | 21) SIGTTIN | 22)SIGTTOU | 23) SIGURG | 24)SIGXCPU | |
25) SIGXFSZ |
26) SIGVTALRM |
27) SIGPROF | 28) SIGWINCH |
29) SIGIO | 30) SIGPWR | 31) SIGSYS | 32) SIGRTMIN |
** 일반적으로 유닉스에서의 signal은 한번 시그널을 받은 후에, 그 수명을 다하기 때문에 다시 시그널을 받으려면 재정의 해줘야 한다
# sigemptyset
시그널 집합 변수의 내용을 모두 제거한다.
int sigemptyset(sigset_t *set);
시그널 집합 변수를 성공적으로 삭제하면 0을 반환, 실패하면 -1을 반환
# sigaddset
시그널 집합 변수에 시그널을 추가하는 함수
(삭제하는 건 sigdelset())
#include <signal.h>
int sigaddset(sigset_t *set, int signum);
집합 변수를 추가하는데 성공하면 0을 반환, 실패하면 -1을 반환
- sigset_t *set: 시그널 집합 변수
- int signum : 시그널 넘버
(*set에 시그널 signum을 추가한다.)
# sigaction
특정 신호를 수신할 때 프로세스가 수행하는 action을 설정, 변경한다.
signal()과 달리 시그널을 객체로 다룰 수 있다.
#include <signal.h>
int sigaction(int signum, const struct sigaction *restrict act, struct sigaction *restrict oldact);
성공하면 0을 반환하고 오류가 발생하면 -1이 반환된다. (errno에 오류의 종류를 저장)
- int signum : 시그널 넘버 (SIGKILL, SIGSTOP을 제외한 모든 시그널이 들어올 수 있다.)
- struct sigaction *act : 새롭게 지정할 프로세스
- struct sigaction *oldact : 새롭게 지정하기 전에 이미 지정되어 있던 프로세스를 이곳에 저장
(** *restrict : 각 포인터가 서로 다른 메모리 공간을 가리키고 있고, 다른 곳에서 접근하지 않으니 컴파일러가 최적화를 하라는 뜻)
sigaction 함수는 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);
};
- void (*sa_handler)(int); : 시그널(signum)을 수신하면 실행할 함수(핸들러)
- void (*sa_sigaction)(int, siginfo_t *, void *); : sa_flags가 SA_SIGINFO일 때 sa_handler 대신 동작하는 핸들러
- sa_handler보다 인자가 더 많다.
- sigset_t sa_mask; : 시그널을 처리하는 동안 블록할 시그널의 마스크를 제공한다.
- int sa_flags; : 각 의미가 다른 여러 종류의 플래그를 사용할 수 있으며 OR 연산자로 여러개를 동시에 지정하여 사용할 수 있다.
- SA_SIGINFO : 시그널 처리기가 하나가 아니라 3개의 인자를 취할 경우 sa_handler대신 sigaction의 siginfo_t를 사용할 수 있다.
- void (*sa_restorer)(void); : 사용하면 안된다.
* sigaction은 안정된 신호체제를 제공한다.
+ siginfo_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; /* 파일 기술자 */
}
[ 참고 : https://www.joinc.co.kr/w/man/2/sigaction ]
# kill
프로세스에 시그널을 전송. 시스템 호출을 사용하여 프로세스 그룹이나 프로세스에 모든 신호를 보낼 수 있다.
(** shell 명령어 kill은 프로세스를 죽인다.)
#include <signal.h>
int kill(pid_t pid, int signum);
성공하면 0을 반환하고, 실패하면 -1을 반환
- pid_t pid : KILL 대상 프로세스 ID
- int signum : 시그널 넘버
pid > 0 : 지정한 프로세스 ID에만 시그널을 전송
pid == 0 : 시그널은 함수를 호출한 프로세스가 속한 그룹의 모든 프로세스에 시그널을 전송
pid == -1 : 프로세스1(init)을 제외하고 함수를 호출한 프로세스가 신호를 보낼 수 있는 권한을 가진 모든 프로세스로 시그널을 전송
pid < 0 && pid != -1 :
(프로세스가 신호를 보낼 수 있는 권한을 가지려면 권한이 있거나(리눅스에서는 대상 프로세스의 사용자 네임스페이스에 CAP_KILL 기능이 있음) 전송 프로세스의 실제 사용자 ID 또는 저장된 사용자 ID와 동일해야 합니다. SIGCONT의 경우 송수신 프로세스가 동일한 세션에 속할 때 충분합니다.)
'42seoul > circle-2' 카테고리의 다른 글
[minitalk] 발전방향 (0) | 2022.02.26 |
---|---|
[ minitalk ] 구현과정 (0) | 2022.02.25 |
[ minitalk ] getpid() | pause() | sleep() | usleep() | exit() (0) | 2022.02.24 |
[minitalk] 1. UNIX signal (0) | 2022.02.22 |
[ minitalk ] 0. 과제이해하기 (0) | 2022.02.16 |
댓글