이번 포스팅에서는 고아 프로세스와 좀비 프로세스에 대해서 알아 보도록 하겠습니다.


고아 프로세스와 좀비 프로세스 정의는 아래와 같습니다.

부모 프로세스가 자식 프로세스보다 먼저 종료되면 자식 프로세스는 고아프로세스가 됩니다.

그리고 자식 프로세스가 종료되었지만 부모 프로세스가 자식 프로세스의 종료 상태를 회수하지 않았을 경우에 자식 프로세스를 좀비 프로세스라고 합니다.


1. 고아 프로세스

부모 프로세스가 자식 프로세스보다 먼저 종료되면 init 프로세스가 자식 프로세스 새로운 부모 프로세스가 됩니다.

종료되는 프로세스가 발생할 때 커널은 이 프로세스가 누구의 부모 프로세스인지 확인한 후, 커널이 자식 프로세스의 부모 프로세스 ID를 1(init 프로세스)로 바꿔 줍니다.

간단한 예제를 통해서 고아 프로세스의 부모 프로세스가 init 프로세스로 바뀌는지 확인해 보도록 하겠습니다.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    
    pid_t childPid;
    int i;
    
    childPid = fork();
    
    if(childPid > 0) {  // 부모 프로세스
        printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid);
        sleep(2);
        printf("부모 종료\n");
        exit(0);
    }
    else if(childPid == 0){  // 자식 코드
        printf("자식 시작\n");
        
        for(i=0;i<10;i++) {
            printf("자식 PID : %ld 부모 PID : %ld\n",(long)getpid(), (long)getppid());
            sleep(1);
        }
        
        printf("자식 종료\n");
        exit(0);
    }
    else {  // fork 실패
        perror("fork Fail! \n");
        return -1;
    }
    
    return 0;
}



실행 결과는 아래와 같습니다.

 

자식 프로세스의 원래 부모 프로세스는 PID 46797 였으나 부모 프로세스가 종료 된 후에는 1로 바뀐 것을 볼 수 있습니다.

init 프로세스는 유닉스 계열의 운영체제에서 부팅 과정 중 생성되는 최초의 프로세스이며 시스템이 종료될때까지 계속 살아있는 데몬 프로세스입니다.

그리고 init 프로세스의 PID는 일반적으로 1입니다. 

고아 프로세스가 작업을 종료하면 init 프로세스가 wait함수를 호출하여 고아 프로세스의 종료 상태를 회수함으로써 좀비 프로세스가 되는것을 방지합니다.


2. 좀비 프로세스

반대로 자식 프로세스가 부모 프로세스 보다 먼저 종료되는 경우가 있습니다. 

자식 프로세스가 exit 시스템 콜을 호출 하면서 종료되면 이 프로세스에 관련된 모든 메모리와 리소스가 해제되어 다른 프로세스에서 사용할 수 있게 됩니다.

자식 프로세스가 종료된 이후에 부모 프로세스가 자식 프로세스의 상태를 알고 싶을 수 있기 때문에 커널은 자식 프로세스가 종료되더라도 최소한의 정보(프로세스 ID, 프로세스 종료 상태 등)를 가지고 있게 됩니다.

부모 프로세스가 좀비 프로세스의 종료상태를 회수하게 되면(wait 시스템콜을 호출을 통하여)  좀비 프로세스는 제거됩니다.

간단한 예제 코드를 보도록 하겠습니다.


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int main() {
    
    pid_t childPid;
    
    childPid = fork();
    
    if(childPid > 0) {  // 부모 프로세스
        printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid);
        sleep(30);
        printf("부모 종료\n");
        exit(0);
    }
    else if(childPid == 0){  // 자식 코드
        printf("자식 시작 PID : %ld\n", (long)getpid());
        sleep(1);
        printf("자식 종료\n");
        exit(0);
    }
    else {  // fork 실패
        perror("fork Fail! \n");
        return -1;
    }
    
    return 0;
}


터미널 창에 아래와 같이 명령어를 입력합니다.

ps aux | grep 'Z' 명령어를 사용하여 좀비 프로세스를 출력합니다.


좀비 프로세스가 쌓이게 되면 리소스의 유출을 야기할 수 있기 때문에 좀비 프로세스 상태를 오래 유지되지 않도록 부모프로세스는 wait 시스템 콜 함수를 사용하여 자식 프로세스의 종료 상태를 읽어들이는 것이 필요합니다.

+ Recent posts