1. 프로세스 상속관계 확인

 - 명령어: ps -f(f는 상세를 나타내는 옵션)

   

 

 

 

 

2. 프로세스의 잘못된 종료상태

 - 좀비(zombi) 프로세스

    부모가 wait를 호출하기전에 자식프로세스가 종료되면(정상종료이던 비정상 종료이던), 이 자식프로세스는 좀비가 된다.

    (부모가 wait를 통해 반환코드를 받을때까지)

    좀비프로세스는 프로세스 테이블 엔트리(process table entry=file descriptor)에 정보가 남아있게 된다.

 - 고아(orphan) 프로세스

    부모가 먼저 종료된 자식프로세스.

    커널은 자동으로 고아프로세스의 부모를 Init프로세스로 묶어준다.

    즉, 고아의 PPID는 1이고 고아는 Init프로세스의 양자가된다. 고아가 양자가 되면 정상종료가 가능해진다.

 

※ 좀비프로세스에 대한 자세한 고찰

좀비프로세스의 정의는 실행이 종료되었지만 아직 삭제되지 않은 프로세스를 말한다.

종료되었지만 삭제되지 않았다는 뜻에 대해서 알아보도도록 하자. 보통 프로세스는 exit 시스템함수를 호출함으로써, 프로세스를 종료시킬려고 한다. 그리고 자신의 모든 자원을 해제 시키게 된다. 그러나 프로세스의 exit status 상태와 PID는 여전히 남아서(커널의 task struct에) 유지되게 된다. 이렇게 하는 몇가지 이유가 있는데, 이렇게 함으로써 부모 프로세스는 자식프로세스에 대한 종료상태등을 가져올수 있어서 자신의 자식프로세스가 어떤 상태로 작업을 마쳤는지에 대한 정보를 확인할수 있기 때문이다. 만약 프로세스가 exit 를 호출하는 즉시 모든 자원을 되돌려줌과 동시에 커널에서 task struct 에서 프로세스 정보를 삭제시켜 버린다면, 부모프로세스는 자신의 자식 프로세스가 어떤 상태로 종료되었는지 알수 없게 될것이다.

출처: https://www.joinc.co.kr/w/Site/system_programing/process/Zombie

 

 

 

 

3. 실습 전 참고할 함수 설명

 

 - getpid, getppid함수

    헤더파일

     - <sys/types.h> //pid_t를 위한 헤더(pid_t=int와 같다)
     - <unistd.h> //getpid, getppid를 위한 헤더

    함수설명

     - pid_t getpid(void);

        // 들어가는 인자값은 없고, 자신의 pid를 pid_t(int)형으로 반환한다(항상 성공이라 에러반환은 없다)
     - pid_t getppid(void);

        // 들어가는 인자값은 없고, 자신의 ppid(부모의 pid)를 pid_t(int)형으로 반환한다(항상 성공이라 에러반환은 없다)

 

  참조
    https://www.ibm.com/support/knowledgecenter/en/ssw_i5_54/apis/getpid.ht

 

 

 

4. 고아 프로세스 실습

 - 실행을 위한 소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <sys/types.h>
#include <wait.h>
 
int main()
{
    pid_t pid;
    printf("I'm the original process : pid = %d, ppid = %d\n", getpid(), getppid());
 
    pid =  fork(); //부모 프로세스의 경우 반환 받는 값은 자식의 pid, 자식의 경우 0값을 받는다
        
    if ( pid != 0 )  {    /* parent process */
        printf("I'm parent process : pid = %d, ppid = %d\n", getpid(), getppid()); 
        //getpid()는 자신의 PID가져오기, getppid() 부모의 PID(즉, PPID) 가져오기
        printf("my child process : pid = %d\n", pid);
    }
    else {                /* child process */
        printf("I'm child process : pid = %d, ppid = %d\n", getpid(), getppid()); 
        sleep(5);
        //5초동안 잠들어 있으니 부모가 먼저 종료된다(즉 자식은 고아가 된다)
    }
        /* parent & child  process */
    printf("pid %d terminates.. \n", getpid());  
    return 0;
}
 
cs

 

 - 실행결과

   

 

    => 커널은 고아들을 모두 init의 양자로 만들어 버린다. 부모가 종료되고 남은 프로세스 2416의 ppid는 1(init의 pid)임을 확인 할 수 있다

 

 

 

 

5. 좀비 프로세스 실습

 - 실행을 위한 소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <wait.h>
 
int main()
{
   pid_t pid;
      
   pid = fork();
 
   if ( pid != 0 )  { /* parent process */
    while(1) sleep(1000);  //부모는 계속 잠듦
   }
   else { /* child  process */
    exit(42); //자식은 바로종료(부모가 종료될 때까지 좀비)
    //42에 대한 특별한 의미는 없는 것 같다
   }
 
}
cs

 

※ exit에 들어가는 인자값에 대한 고찰

 https://stackoverflow.com/questions/39366400/why-is-it-exit42

 

 - 실행결과

먼저 ./a.out&명령으로 실행파일을 백그라운드에서 동작시켰다

 

   

 

위 그림을 보면 ps -f명령으로 2515프로세스가 자식프로세스이며, ps u 명령으로 좀비상태임을 알 수 있다

kill명령으로 부모 프로세스를 죽이면 자식프로세스의 남은 정보또한 회수되어 프로세스의 정보가 사라져있다(아래 사진 참조)

 

   

 

반대로 kill명령을 사용해서 자식을 종료할 경우, 이미 종료되었기 때문에 여전히 정보가 남아있다(소용이 없다)(아래 사진 참조)

   

 

 

 

 

 

 

+ Recent posts