현생/TCP 소켓 프로그래밍
10-5 시그널 핸들링 - sigaction, 좀비 프로세스 해결 [TCP/IP][C][LINUX]
푸더기
2022. 1. 30. 13:42
반응형
sigaction 함수는 signal 함수를 대체할 수 있고 더 안정적입니다. sigaction 함수는 유닉스 계열 운영체제 별 동작방식에 따른 차이를 보이지 않기 때문입니다. 따라서 요즘은 signal 함수 대신 sigaction 함수를 사용합니다.
#include<signal.h>
int sigaction(int signo, const struct sigaction * act, struct sigaction * oldact);
//success: 0 fail: -1
//signo: 시그널의 정보
//act : 시그널 발생시 호출될 함수의 정보
//oldact: 이전에 등록되었던 시그널 핸들러의 함수 포인터를 얻는데 사용, 필요 없으면 0 전달
위 함수의 호출을 위해서는 sigaction이라는 이름의 구조체를 선언 및 초기화해야합니다.
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
}
sa_handler에는 함수 포인터 값을 저장하고 sa_mask의 모든 비트를 0으로, sa_flags도 0으로 초기화 하면 됩니다.
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void timeout(int sig){
if(sig==SIGALRM)
puts("Time out");
alarm(2);
}
int main(int argc, char *argv[]){
int i;
struct sigaction act;
act.sa_handler=timeout;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGALRM, &act, 0);
alarm(2);
for(i=0; i<3; i++){
puts("wait...");
sleep(100);
}
return 0;
}
sigaction 함수를 사용한 예제코드입니다. sigaction 구조체를 설정해주고, 2초마다 Time out을 출력하는 시그널핸들링을 해주었습니다. 앞서 10-4에서 보았듯이 시그널이 발생하면 블로킹이 해제되므로 sleep(100)에 의해 총 300초를 잠들어야하지만 10초 이내로 실행이 종료됩니다.
이제 sigaction 함수를 이용해서 좀비 프로세스를 소멸시키는 방법을 알아보겠습니다.
자식 프로세스가 종료된 상황에 대한 시그널 이름이 SIGCHLD임을 이용하면 위의 내용만으로 손쉽게 예제코드를 작성할 수 있습니다.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
void read_childproc(int sig){
int status;
pid_t id = waitpid(-1, &status, WNOHANG);
if(WIFEXITED(status)){
printf("Removed proc id: %d\n",id);
printf("Child send: %d \n",WEXITSTATUS(status));
}
}
int main(int argc, char *argv[]){
pid_t pid;
struct sigaction act;
act.sa_handler=read_childproc;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGCHLD, &act, 0);
pid=fork();
if(pid==0){ //자식 프로세스 실행 영역
puts("Hi! I'm child process");
sleep(10);
return 12;
}
else{ //부모 프로세스 실행 영역
printf("Child proc id: %d \n",pid);
pid=fork();
if(pid==0){ //자식2 프로세스 실행 영역
puts("Hi! I'm child process");
sleep(10);
exit(24);
}
else{ // 부모 프로세스 실행 영역
int i;
printf("Child proc id: %d \n", pid);
for(i=0; i<5; i++){
puts("wait...");
sleep(5);
}
}
}
return 0;
}
자식 프로세스의 종료, 즉 SIGCHLD 시그널이 발생하면 act 함수가 실행되도록 짠 예제코드입니다. 첫 번째 자식은 10초를 기다린 후 12를 반환하고 두 번째 자식은 10초를 기다린 후 24를 인자로 가진 exit를 호출합니다. 둘 모두 정상적으로 종료되어 값을 전달하게 됩니다.
반응형