fork() 시스템 콜은 하나의 프로세스를 두 개의 프로세스로 분리하는 데 사용됩니다. fork() 함수가 0을 반환하면 자식 프로세스이고, 그렇지 않으면 부모 프로세스입니다.
이번 예제에서는 프로세스를 네 번 분할하고, 이를 아래에서 위로(bottom-up), 즉 손자 → 자식 → 부모 순서로 실행하는 방법을 알아보겠습니다.
동작 원리
먼저 fork() 함수를 연속으로 두 번 호출합니다. 첫 번째 fork() 호출로 하나의 자식 프로세스가 생성되고, 두 번째 fork() 호출로 또 다른 자식 프로세스가 생성됩니다. 이후 내부의 fork()는 자동으로 이들의 손자(grandchild) 프로세스까지 만들어냅니다. 결과적으로 메인 프로세스 1개, 자식 프로세스 2개, 손자 프로세스 1개, 총 4개의 프로세스가 만들어집니다.
여기에 wait() 함수와 sleep() 함수를 사용해 실행 지연을 주면, 프로세스들이 의도한 대로 아래에서 위로 순차적으로 종료되도록 제어할 수 있습니다.
예제 코드
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
int main() {
pid_t id1 = fork(); // 연속된 두 번의 fork로 4개 프로세스 생성: 부모, 자식 둘, 손자 하나
pid_t id2 = fork();
if (id1 > 0 && id2 > 0) { // 두 값 모두 0이 아니면 부모 프로세스
wait(NULL);
wait(NULL);
cout << "Ending of parent process" << endl;
} else if (id1 == 0 && id2 > 0) { // 첫 번째 값이 0이면 첫 번째 자식
sleep(2); // 두 번째 자식이 먼저 실행되도록 2초 대기
wait(NULL);
cout << "Ending of First Child" << endl;
} else if (id1 > 0 && id2 == 0) { // 두 번째 값이 0이면 두 번째 자식
sleep(1); // 1초 대기
cout << "Ending of Second child process" << endl;
} else {
cout << "Ending of grand child" << endl;
}
return 0;
}
실행 결과
soumyadeep@soumyadeep-VirtualBox:~$ ./a.out Ending of grand child Ending of Second child process Ending of First Child Ending of parent process soumyadeep@soumyadeep-VirtualBox:~$
코드 설명
실행 결과를 보면 가장 마지막에 생성된 손자 프로세스가 먼저 종료되고, 그다음 두 번째 자식, 첫 번째 자식, 마지막으로 부모 프로세스가 종료되는 것을 확인할 수 있습니다.
- 부모 프로세스(
id1 > 0 && id2 > 0):wait(NULL)을 두 번 호출하여 모든 자식 프로세스가 종료될 때까지 기다립니다. - 첫 번째 자식(
id1 == 0 && id2 > 0):sleep(2)로 2초간 대기한 후, 자신의 자식(손자)이 끝나기를wait()로 기다린 뒤 종료합니다. - 두 번째 자식(
id1 > 0 && id2 == 0):sleep(1)로 1초간 대기한 후 종료합니다. - 손자 프로세스: 별도의 대기 없이 즉시 종료됩니다.
이처럼 wait()와 sleep()을 적절히 조합하면 여러 프로세스의 실행 및 종료 순서를 효과적으로 제어할 수 있습니다.