반응형
lxc-monitor.c - double fork 사용
- 사람들이 하는 흔한 실수 중 하나는, 자식 프로세스의 종료를 기다리는
waitpid()
를 호출하지 않고 자식 프로세스를 포크하는 것이다.wait()
호출을 하지 않으면, 자식 프로세스는 종료 후 좀비 프로세스가 된다. 왜냐하면 그것(자식)의 부모 프로세스가 시스템에서 자식의 프로세스 정보를 cleanup 하지 않기 때문이다. 좀비 프로세스가 시스템의 PID를 차지하므로 시스템에서 사용가능한 PID를 줄인다. 좀비는ps
명령으로 프로세스를 확인하면 '비활성화됨(defunct)'로 표시된다.
- 그러나 때로는 부모 프로세스가 자식 프로세스를 오랫동안 기다리지 않는 것을 원한다. '좀비 프로세스를 만들지 않기', '자식 프로세스가 종료 될 때까지 기다리지 말기'를 모두 달성할 수 있는 방법이 있는데, 그 방법이 바로
double fork
하는 것이다.
- 부모 프로세스(예 : A)가 자식 프로세스를 '무언가'로 fork하고자 할 때 간단한 아이디어가 있다. 프로세스 A는 '무언가'를 직접 수행하는 프로세스를 fork하지 않는다. 프로세스 A는 먼저 하위 프로세스(예 : B)를 분기한 다음 프로세스는 자식 프로세스(예 : C)를 '무언가'로 포크하고 프로세스 B는 프로세스 C가 만들어 지자 마자 종료한다.
- 이런식으로, 프로세스 A는 단지 짧은 시간 동안 프로세스 B를 기다리면 된다. 같은 시간에 부모 프로세스가 없으므로(프로세스 B가 죽음(dead)), 시스템은 프로세스 C를 초기화 프로세스에
'rechild'
한다. init 프로세스는 자식 프로세스에wait()
를 호출하여 좀비 프로세스 문제를 해결한다.
void func()
{
pid_t pid1;
pid_t pid2;
int status;
if (pid1 = fork()) {
/* parent process A */
waitpid(pid1, &status, NULL);
} else if (!pid1) {
/* child process B */
if (pid2 = fork()) {
exit(0);
} else if (!pid2) {
/* child process C */
execvp("something");
} else {
/* error */
}
} else {
/* error */
}
}
-
궁금한 것 두가지
-
부모가 먼저 죽는 경우 어떻게 되나?
- 부모가 먼저 죽으면 자식은 고아가 되고, 이 고아 프로세스들은 init 프로세스의 자식이 된다. 즉, 자식이 살아있는데 부모가 죽으면, 자식의 부모가 init 프로세스로 자동 변경된다.
-
자식이
waitpid()
호출 전에 죽으면 어떻게 되나?- 자식이 먼저 죽었는데 부모가
waitpid()
로 이를 해제해주지 않으면 좀비 프로세스가 되고, 그 후waitpid()
를 호출하는 순간 바로 리턴되면서 자식의 리소스가 해제된다.
- 자식이 먼저 죽었는데 부모가
-
-
결국 정리해보면 다음과 같다.
- A 프로세스는 fork 하여 자식 프로세스 B를 만든다.
- B프로세스는 다시 fork 하여 자식 프로세스 C를 만든다.
- B프로세스는 C가 만들어지자 마자 종료하고, 프로세스 C는 부모 프로세스(B)가 죽었기 때문에 부모가 init으로 변경된다.
- A 프로세스는 자식 프로세스 B를
waitpid()
를 통해 정상적으료 종료시킨다.
-
참고
반응형
'오픈 소스 > LXC' 카테고리의 다른 글
[LXC] lxc-monitor.c 분석 (0) | 2019.05.09 |
---|---|
[LXC] 수동 설치 - lxc-net 오류 해결 (0) | 2019.04.16 |