Engineering
Zombie 프로세스를 좀처럼 볼 수 없는 이유?
2019년 9월 19일
원문에서 보기 ↗새로운 프로세스를 만들 때 리눅스에서는 fork()를 사용합니다. fork()를 통해서 부모 프로세스는 자식 프로세스를 생성하고, 자식 프로세스에서 실제 실행하려는 프로그램을 exec()을 통해서 실행합니다.
자식 프로세스가 exit()를 호출하고 죽으면, 부모 프로세스는 waitpid()를 명시적으로 호출해서, 이 자식 프로세스의 exit 값을 가져가야 합니다.
자식 프로세스가 exit()를 호출하였으나, 부모 프로세스가 waitpid()로 자식 프로세스의 pid를 수거(reaping) 하지 않은 경우에, 이 자식 프로세스는 zombie 상태가 됩니다.
$ ps -e -o pid,stat,comm | grep a.out
32499 S+ a.out
32500 Z+ a.out <defunct>
하지만 이런 zombie 프로세스는 좀처럼 볼 수 없습니다. 보통은 부모 프로세스가 waitpid로 잘 처리하도록 잘 짜여 있기 때문입니다.
또는 이런 zombie 프로세스가 생기더라도, 부모 프로세스가 종료되면 커널은 이 zombie 프로세스를 init(또는 systemd) 프로세스의 자식으로 입양시키게 됩니다. init이나 systemd는 주기적으로 waitpid()를 통해서 zombie 프로세스의 눈을 감겨줍니다. (https://en.wikipedia.org/wiki/Zombie_process 참조)
이런 상황을 볼 때, 여러분이 zombie 프로세스를 볼 수 있는 상황은 딱 2개입니다.
- 부모 프로세스가 살아 있으면서도 명시적으로 자식 프로세스에 대해 waitpid 호출하지 않는 경우,
- systemd나 init이 ~~맛이 가서~~오동작을 해서 zombie 프로세스를 제대로 회수하지 않는 경우,
zombie를 직접 보고 싶으시면 아래 코드를 이용하세요. 컴파일 후 실행하고 5초 뒤에 ps로 해당 바이너리 상태를 보시면 됩니다.
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main()
{
int pid;
int status;
pid = fork();
//signal(SIGCHLD, SIG_IGN);
if (pid == 0)
{
sleep(5);
printf("I will be back %d\n", getpid());
exit(0);
}
else if(pid > 0)
{
printf("Im parent %d\n", getpid());
printf("Press any key\n");
getchar();
/*
while(1)
{
printf("Im sleeping\n");
sleep(1);
}
*/
}
else
{
perror("fork error :");
}
}
위 코드는 https://www.joinc.co.kr/w/Site/system_programing/process/Zombie 에서 가져왔습니다.