2009.05.31 16:27

[Linux C++] 프로세스 & 좀비 프로세스

1. 좀비 프로세스란?
- 프로세스 종료 후, 메모리에서 사라지지않는 프로세스를 말합니다.

2. 좀비 프로세스가 생성되는 이유?
- 자식 프로세스는 수행종료 후 부모 프로세스에게 실행 결과에 대한 리턴값을 넘겨줘야 합니다.
그리고 부모 프로세스 역시 이 리턴값을 받아야 자식 프로세스가 좀비가 되는 문제를 막을 수 있습니다.


첫번째 그림은 자식 프로세스가 실행을 마치고, 실행 결과에 대한 리턴값(0)을 커널에 넘겼지만,
부모 프로세스가 이를 받지 않았습니다. 그래서 자식 프로세스는 좀비상태가 됩니다.

두번째 그림은 커널이 부모 프로세스에게 리턴값(0)을 전달하고,
그제서야 자식 프로세스가 소멸되는 것을 나타낸 것입니다.

사용자 삽입 이미지

리눅스 콘솔에서 ps -u 라고 입력하면 실행중인 프로세스 목록을 볼 수 있습니다.
위 스샷을 보면 STAT 에 Z 라고 적힌 프로세스가 있습니다.
이것이 Zombie, 좀비 프로세스입니다.
자식 프로세스가 실행을 마쳤지만, 부모 프로세스가 리턴값을 받지않은 결과져.

- 좀비 프로세스의 소멸 1
1. 소멸 방법
- 부모 프로세스에서 자식 프로세스의 리턴값을 요구합니다.
2. wait 함수의 사용
- 장점 : 사용하기 간단합니다.
- 단점 : 무한루프에 빠질 수 있습니다.

  1. #include <sys/types.h>   
  2. #include <sys/wait.h>   
  3.   
  4. pid_t wait(int * status)   

  1. /*  
  2.  * wait.c  
  3.  * Written by SW. YOON  
  4.  */  
  5. #include <stdio.h>   
  6. #include <sys/wait.h>   
  7. #include <sys/types.h>   
  8.   
  9. int main(int argc, char **argv)   
  10. {   
  11.   pid_t pid, child;   
  12.   int data=10;   
  13.   int state;   
  14.   
  15.   pid=fork();   
  16.   if(pid<0)   
  17.     printf("fork 실패 프로세스 id : %d \n", pid);   
  18.   
  19.   printf("fork 성공 프로세스 id : %d \n", pid);   
  20.   
  21.   if(pid==0) /* 자식 프로세스라면 */  
  22.     data+=10;   
  23.   else       /* 부모 프로세스라면 */  
  24.   {   
  25.     data-=10;   
  26.     child=wait(&state); /* 자식 프로세스의 종료 대기 */  
  27.     printf("자식 프로세스 ID = %d \n", child);   
  28.     printf("리턴 값 = %d \n", WEXITSTATUS(state));   
  29.     sleep(20); /* 프로세스 상태 확인을 위해서 */    
  30.   }   
  31.   
  32.   printf("data : %d \n", data);   
  33.   return 0;   
  34. }  
./wait & 명령으로 프로그램을 수행합니다.
& 를 붙이게 되면, 프로그램 수행 후에도 사용자 입력을 받을 수 있는 상태가 됩니다.

우선, pid=fork() 로 자식 프로세스를 생성합니다.
pid == 0 판단하여, 자식 프로세스라면 data+=10
부모 프로세스라면 data-=10 을 수행합니다.

여기서 자식 프로세스는 data 값(20)을 출력하고 0을 리턴합니다.

부모 프로세스는 child = wait(&state) 로 자식 프로세스의 리턴값을 받습니다.
* 만약, 여기서 자식 프로세스가 리턴하지 못하면, 부모 프로세스는 무한대기상태에 빠집니다.

중간에 [1] 15299 라고 출력되는 것은 /wait & 수행시 나타나는 것으로
어떤 프로세스의 수행이 끝났을 때 프로세스 id 값이 출력되는 것 같습니다 ;;

사용자 삽입 이미지

- 좀비 프로세스의 소멸 2
1. 소멸 방법
- 부모 프로세스에서 자식 프로세스의 리턴값을 요구합니다.
2. waitpid 함수의 사용
- wait 함수가 가지고 있는 무한대기상태의 문제점을 해결합니다.
  1. #include <sys/types.h>   
  2. #include <sys/wait.h>   
  3.   
  4. pid_t waitpid(pid_t pid, int * status, int options)   

  1. /*  
  2.  * waitpid.c  
  3.  * Written by SW. YOON  
  4.  */  
  5.   
  6. #include <stdio.h>   
  7. #include <sys/wait.h>   
  8. #include <sys/types.h>   
  9.   
  10. int main(int argc, char **argv)   
  11. {   
  12.   pid_t pid, child;   
  13.   int data=10;   
  14.   int state;   
  15.   
  16.   pid=fork();   
  17.   if(pid<0)   
  18.     printf("fork 실패, 프로세스 id : %d \n", pid);   
  19.   
  20.   printf("fork 성공, 프로세스 id : %d \n", pid);   
  21.   
  22.   if(pid==0) /* 자식 프로세스라면 */  
  23.   {   
  24.     data+=10;   
  25.     sleep(10); /* 종료를 10초 지연 */  
  26.   }   
  27.   else       /* 부모 프로세스라면 */  
  28.   {   
  29.     data-=10;   
  30.     do{   
  31.       sleep(3);   
  32.       puts("3초 대기");   
  33.       child=waitpid(-1, &state, WNOHANG);   
  34.     }while(child == 0);   
  35.   
  36.     /* 종료한 자식 프로세스 상태정보 출력 */  
  37.     printf("Child process id = %d, return value = %d \n\n", child, WEXITSTATUS(state));   
  38.   }   
  39.   
  40.   printf("data : %d \n", data);   
  41.   return 0;   
  42. }  
코드에 큰 차이는 없습니다.
child=waitpid(-1, &state, WNOHANG); 에 대해서만 설명하겠습니다.

waitpid 에 첫번째 인자로
-1 을 주게되면, 특정 프로세스를 기다리는게 아니라 모든 프로세스로부터 리턴값을 받는다는 의미입니다.
두번째 인자의 state 는 wait 과 같은 의미로써, 리턴값을 저장합니다.
세번째 인자의 WNOHANG 은 프로세스로부터 리턴값을 받지 못하면 0 을 리턴한다는 의미입니다.

결국 while(child==0) 루프를 돌리고 있으므로,
이 코드 역시 위의 wait 예제와 같은 것이라고 봐도 무방하겠습니다.

사용자 삽입 이미지


출처 : http://thx4alice.tistory.com/

Trackback 0 Comment 0