부모 프로세스에서 자식 프로세스의 종료를 계속 확인하기에는 비효율적입니다. 자식 프로세스의 종료를 인식하는 주체는 운영체제이므로 운영체제가 부모 프로세스에게 자식 프로세스의 종료를 알릴 수 있다면 더 효율적일 것입니다.
#include<signal.h>
void (*signal(int signo, void(*func)(int)))(int);
// 시그널 발생시 호출되도록 이전에 등록한 함수의 포인터 반환
위 함수를 시그널 등록 함수라고 표현하는데요, 프로세스가 자식 프로세스의 종료 발생 시 특정 함수의 호출을 운영체제에게 요구하는 "시그널 등록"을 하기 때문입니다.
위 함수를 정리하면 다음과 같습니다.
함수 이름: signal
매개변수 선언: int signo, void(*func)(int)
반환형 : 매개변수형이 int이고 반환형이 void인 함수 포인터
signal함수를 통해서 등록 가능한 특정 상황과 그 상황에 할당된 상수의 일부입니다.
SIGALRM : alarm 함수 호출을 통해 등록된 시간이 된 상황
SIGINT : CTRL+C가 입력된 상황
SIGCHLD : 자식 프로세스가 종료된 상황
signal(SIGCHLD, exfunc);
예를 들어 자식 프로세스가 종료되면 exfunc 함수를 호출해달라는 상황일 때 signal 함수의 호출은 위와 같이 할 수 있습니다. 이때 exfunc 함수는 매개변수형이 int, 반환형이 void여야 합니다.
#include<unistd.h>
unsigned int alarm(unsigned int seconds);
// 0 또는 SIGALRM 시그널이 발생하기까지 남아있는 시간 초 단위 반환
위 특정 상황중 SIGALRM에서 alarm 함수가 등장하는데, 전달된 수에 해당하는 시간이 지나서 SIGALRM 시그널이 발생합니다. 만약 0을 인자로 전달하면 이전에 설정된 SIGALRM 시그널 발생 예약이 취소됩니다. 다만 위 함수호출로 시그널 발생을 예약만 해놓고 signal 함수호출을 통해 이 시그널의 함수를 지정하지 않으면 프로세스가 종료됩니다.
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void timeout(int sig){
if(sig==SIGALRM)
puts("Time out");
alarm(2);
}
void keycontrol(int sig){
if(sig==SIGINT)
puts("CTRL+C pressed");
}
int main(int argc, char *argv[]){
int i;
signal(SIGALRM, timeout);
signal(SIGINT, keycontrol);
alarm(2);
for(i=0; i<3; i++){
puts("wait...");
sleep(100);
}
return 0;
}
signal의 예제코드입니다. 이 함수를 실행하면 wait를 출력하고 100초를 기다려야하는데, 얼마 안 기다리고 Time out을 출력하는 걸 볼 수 있습니다. 이 이유는 시그널 핸들러 호출을 위해 sleep 함수의 호출로 블로킹상태에 있던 프로세스가 깨어났기 때문입니다.
'현생 > TCP 소켓 프로그래밍' 카테고리의 다른 글
10-6 멀티프로세스 기반 다중접속 서버 구현 [TCP/IP][C][LINUX] (0) | 2022.01.30 |
---|---|
10-5 시그널 핸들링 - sigaction, 좀비 프로세스 해결 [TCP/IP][C][LINUX] (0) | 2022.01.30 |
10-3 좀비 프로세스 해결법 [TCP/IP][C][LINUX] (0) | 2022.01.27 |
10-2. 프로세스의 현재 상태 확인 방법과 후면처리 [LINUX] (0) | 2022.01.27 |
10-1. 다중접속서버의 필요성과 멀티프로세스 [TCP/IP][C][LINUX] (0) | 2022.01.26 |