본 글은 윤성우의 TCP/IP 소켓 프로그래밍 책을 참고하였습니다.

순서

I. 좀비 프로세스 개념
1. 좀비 프로세스란?
2. 좀비 프로세스 생성이유

II. 좀비 프로세스의 소멸 방법
1. wait() 함수
2. waitpid() 함수


주의!! 본 글에서 설명하는 멀티 프로세스 기반 서버는 Windows에는 지원하지 않는 Linux 방식입니다. 

I. 좀비 프로세스 개념


1. 좀비(Zombie) 프로세스란?

왜 좀비일까? 죽어도 죽지않는 그런 의미일 것이다.

파일로 예를들면,
파일을 열고 작업을 한 뒤에 닫지 않으면 계속 열려있는 상황이 발생하는 것이다.

프로세스도 동일하다.

프로세스가 생성되고 일을 다 마치면 사라져야 하는데, 남아서 메모리를 계속 차지하게 된다.

따라서 우리는 좀비프로세스를 꼭 제거해주어야 하는 것이다.


2. 좀비 프로세스의 생성 이유

 

좀비 프로세스는 다음과 같이 두 경우에 생긴다.

1. 인자를 전달하면서 exit를 호출하는 경우
2. main 함수에서 return문을 실행하면서 값을 반환해 끝내는 경우

위 두 경우의 exit과 main의 return 모두 운영체제로 값이 전달되는데,
이 때 운영체제는 이 값이 자식 프로세스를 생성한 부모 프로세스에게 전달될 때 까지
자식 프로세스를 소멸 시키지 않는다.

이 어려운 설명을 그림으로 나타내면

좀비 프로세스를 소멸시키기 위해서는, 위 그림처럼 Parent로 값들이 전달되어야한다.

하지만!!

그냥 가만히 있으면 Parent로 가지 않는다.

부모 프로세스의 함수 호출이 있어야 운영체제가 위 그림의 2번 과정을 진행한다.
이 때, 함수가 바로 뒤에 설명할 wait(), waitpid() 함수이다.

+) 좀비 프로세스는 "ps"(리눅스 콘솔 명령어)로 상태를 보면 STAT가 Z+로 되어있다.
++) 후면처리( 백그라운드 상태로 실행 ) ./Programname &

 


II. 좀비 프로세스의 소멸방법


1. wait() 함수

#include <sys/wait.h>

pid_t wait(int * statloc);
    --> 성공 시 종료된 자식 프로세스의 ID, 실패 시 -1 반환
    
    ㄴ. statloc : 자식 프로세스의 정보가 담긴 int 변수의 주소
    
    
함수가 불려진 이후 인자의 변수에는 두 매크로 함수의 정보가 들어있다.
    
statloc이 가지고 있는 매크로함수 정보
    
WIFEXITED(statloc)   : 자식 프로세스가 정상 종료한 경우 참(True) 반환.
WEXITSTATUS(statloc) : 자식 프로세스의 전달 값을 반환한다.

중요!! wait() 함수는 호출 시점에 종료된 자식 프로세스가 없으면 Blocking상태에 놓인다!

두 가지 매크로 함수를 사용하기 위해서 wait()를 이용한 예시 코드를 보자.

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

int main(){
    int status;
    // 자식 프로세스1 생성
    pid_t pid=fork();
    
    // 자식 프로세스1은 3 반환
    if(pid==0) return 3;
    
    else{
        printf("Child1 PID : %d\n", pid);
        
        // 자식 프로세스2 생성
        pid = fork();
        
        // 자식 프로세스2는 7인자로 탈출
        if(pid==0) exit(7);
        
        else{
            printf("Child2 PID : %d\n", pid);
            
            // 자식 프로세스1 소멸위해 값 요청
            wait(&status);
            // 매크로 함수 사용법
            if(WIFEXITED(status)) printf("Child1 send : %d\n",WEXITSTATUS(status));
            
            // 자식 프로세스2 소멸위해 값 요청
            wait(&status);
            if(WIFEXITED(status)) printf("Child2 send : %d\n",WEXITSTATUS(status));
            
            // 부모 30초간 종료 안시키는데 이때 리눅스 콘솔에서 좀비 확인해봐도 된다.
            sleep(30);
        }
    }
    return 0;
}

결과
Child1 PID : 12337 // 값 다를 수 있음
Child2 PID : 12338 // 값 다를 수 있음
Child1 send : 3
Child2 send : 7

 


2. waitpid() 함수

#include <sys/wait.h>

pid_t waitpid(pid_t pid, int* statloc, int options);
    --> 성공 시 종료된 자식 프로세스의 ID(또는 0), 실패 시 -1 반환
    
    ㄴ. pid     : 종료를 확인하고자 하는 자식 프로세스의 ID 전달
                  만약 -1을 전달하면 wait처럼 임의의 자식 프로세스 종료대기
                  
    ㄴ. statloc : wait의 statloc처럼 정보를 담을 int 변수 주소를 전달한다.
    
    ㄴ. options : 위의 헤더에 선언된 상수 WNOHANG을 인자로 전달하면,
                  Blocking상태에 있지 않고 0 반환하며 빠져나온다.
                  
    
statloc이 가지고 있는 매크로함수 정보
    
WIFEXITED(statloc)   : 자식 프로세스가 정상 종료한 경우 참(True) 반환.
WEXITSTATUS(statloc) : 자식 프로세스의 전달 값을 반환한다.

wait()와 waitpid()의 가장 큰 차이점은 다음과 같다.
waitpid()에서는 함수 호출시 Blocking에 걸리지 않을 수 있다(Option) !!

statloc 변수에 담기는 매크로 함수는 wait와 같다.

+ Recent posts