- 부모 프로세스에서 waitpid 함수를 계속 호출하여 자식 프로세스가 종료되기를 기다리는 것은 효율적인 방법이 아닐 수 있음
- 시그널 핸들링(signal handling): 자식 프로세스의 종료를 인식하는 운영체제가 부모 프로세스에 자식 프로세스의 종료를 알려야 함
- JAVA의 경우 프로세스나 쓰레드의 생성방법을 프로그래밍 언어 차원에서 제공하지만 C, C++ 의 경우 ANSI표준에서 함수를 제공하지 않음
- 프로세스, 쓰레드의 경우 운영체제 차원에서 지원되는데 JAVA는 플랫폼 독립의 특성을 가지고 있어 운영체제에 상관없이 동일하게 적용되는 프로세스, 쓰레드의 생성방법을 제공
- signal 등록: 부모 프로세스에서 자식 프로세스 종료 시 특정 함수의 호출을 운영체제에게 요구
#include <signal.h>
void (*signal (int sig, void (*func)(int)))(int);
→ signal 발생 시 호출되도록 이전에 등록된 함수의 포인터 반환
- signal(int sig, void(*func)(int)) 함수의 함수 포인터형
- 매개변수가 int, void형을 반환하는 함수 포인터 반환
- sig: 특정 상황에 대한 정보
- void (*func)(int): 특정 상황에서 호출될 함수의 포인터
- sig의 상황 발생 시 func함수 호출
FLAG |
의미 |
SIGALRM |
alarm 함수호출을 통해서 등록된 시간이 된 상황 |
SIGINT |
CTRL+C가 입력된 상황 |
SIGCHLD |
자식 프로세스가 종료된 상황 |
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
→ 0 또는 SIGALRM signal이 발생하기까지 남아있는 시간을 초 단위로 반환
- 매개변수에 전달된 시간이 지나서 SIGALRM signal이 발생하고 0을 전달하면 이전에 설정된 SIGALRM signal 발생의 예약이 취소
- 위의 함수를 통해서 SIGALRM signal 발생을 예약해놓고 SIGALRM signal이 발생했을 때 호출될 함수를 등록하지 않으면 프로세스가 바로 종료
// 실행창
// 실행창
CTRL+C 입력 시 실행창
- 메인 함수에서 시그널의 발생과 핸들러 함수의 호출을 보기 위해 100초간 3번 sleep함수를 호출하고 종료
- signal이 발생하면 시그널 핸들러 함수의 호출을 위해 sleep 함수의 호출로 blocking 상태에 있던 프로세스가 깨어나고 다시 잠들지 않으므로 sleep함수를 반복하여 호출
- sigaction 함수를 이용한 시그널 핸들링
- signal 함수는 유닉스 계열의 운영체제 별로 동작방식에 있어 차이가 있지만 sigaction 함수는 차이를 보이지 않음
#include <signal.h>
int sigaction(int sig, const struct sigaction *__restrict__ new, struct sigaction *__restrict__ old);
→ 성공 시 0, 실패 시 -1 반환
- sig: signal의 정보
- _restrict_new: 매개변수로 전달된 signal 발생 시 호출될 함수
- _restrict_old: 이전에 등록되었던 signal 핸들러의 함수 포인터를 얻는데 사용되는 인자, 필요없다면 0
struct sigaction {
void (*sa_handler)(int); // 시그널 핸들러의 함수 포인터값
sigset_t sa_mask;
int sa_flags;
void (*sa_sigaction)(int, siginfo_t *, void *);
};
- sa_mask, sa_flags(signal관련 옵션 및 특성의 지정)은 모든 비트를 0으로 초기화
// 실행창
- signal handling을 통한 좀비 프로세스의 소멸
// 실행창
- 2개의 자식 프로세스를 생성한뒤 2번의 시그널을 통한 시그널 핸들러 함수(자식 프로세스 소멸) 호출을 위해 부모 프로세스에서 적어도 2번의 sleep함수 호출해야함