Development/C

c - waitpid() 함수

linuxism 2013. 11. 3. 13:16


설명

wait()함수처럼 자식 프로세스가 종료될 때까지 대기합니다. 차이점은 wait() 함수가 자식 프로세스 중 어느 하나라도 종료되면 복귀되지만, 즉 대기에서 풀리지만 waitpid()는 특정 자식 프로세스가 종료될 때까지 대기 합니다.

또한 wait()는 자식 프로세스가 종료될 때까지 block되지만 waitpid()는 WNOHANG 옵션을 사용하면 block되지 않고 다른 작업을 진행할 수 있습니다.

pid_t waitpid(pid_t pid, int *status, int options);

첫번째 인수 pid_t pid는 감시 대상인 자식 프로세스의 ID입니다. 이 ID값에는 자식 프로세스 ID외에도 아래와 같은 값을 지정할 수 있습니다.

pid설명
-1여러 자식 중 하나라도 종료되면 복귀, wait()와 같은 처리
0현재의 프로세스의 그룹 ID와 같은 그룹의 자식 프로세스가 종료되면 복귀
양수pid에 해당하는 자식 프로세스가 종료되면 복귀

3번재 인수 options는 여러 상수 값이 있습니다만 WNOHANG와 0을 많이 사용합니다.

options설명
WNOHANG자식 프로세스가 종료되었는지 실행 중인지만 확인하고 바로 보귀. 즉, 부모프로세스는 bock되지 않음
0자식 프로세스가 종료될 때까지 block됨. 즉, wait()와 같은 처리

WNOHANG를 사용했을 경우 waitpid()는 자식 프로세스의 종료 상태를 확인하고 바로 복귀합니다. 만일 자식 프로세스가 활동 중이라면 0을 반환하고, 종료되면 자식 프로세스의 ID가 반환됩니다.

헤더wait.h
형태pid_t waitpid(pid_t pid, int *status, int options);
인수pid_t pid감시할 자식 프로세스 ID
 int *status자식 프로세스의 종료 상태 정보
 int options대기를 위한 옵션
반환int

정상: 종료된 자식 프로세스 ID
실패: -1
WNOHANG를 사용했고 자식 프로세스가 종료되지 않았다면: 0

예제

예제를 두가지 올립니다. 첫번째 예제는 두번째 생성한 자식 프로세스가 종료될 때까지 대기하도록 하며, 두번째 예제는 자식 프로세스가 종료될 때까지 부모 프로세스도 제 할일을 하도록 하겠습니다.

첫번째 예제입니다. 두개의 자식 프로세스를 생성하는데, 첫번째 자식 프로세스는 5까지 카운트하고 두번째 자식 프로세스는 10까지 카운트합니다. 부모 프로세스는 10까지 카운트하는 자식 프로세스가 종료될 때 까지 대기합니다.

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

int main()
{
   int   counter  = 1;
   int   status;
   pid_t pid;
   pid_t pid_child;
       
   printf( "부모: 첫번째 자식 프로세스를 생성합니다.\n");    
   pid   = fork();

   switch( pid)
   {
      case -1  :
      {
         printf( "자식 프로세스 생성 실패\n");
         return -1;
      }
      case 0   :
      {
         printf( "1st: 저는 첫번째 자식 프로세스로 5까지 카운트하고 종료하겠습니다.\n");
         while( 6 > counter )
         {
            printf( "1st: %d\n", counter++);
            sleep( 1);
         }
         return 99;
      }
      default  :
      {
         printf( "부모: 두번째 자식 프로세스를 생성합니다.\n");    
         pid   = fork();
      
         switch( pid)
         {
            case -1  :
            {
               printf( "자식 프로세스 생성 실패\n");
               return -1;
            }
            case 0   :
            {
               printf( "2nd: 저는 두번째 자식 프로세스로 10까지 카운트하고 종료하겠습니다.\n");
               while( 11 > counter )
               {
                  printf( "2nd: %d\n", counter++);
                  sleep( 1);
               }
               return 99;
            }
            default  :
            {
               printf( "부모: 저는 부모 프로세스로 자식 프로세스 작업이 \
끝날 때 까지 대기합니다..\n");
      
               pid_child   = waitpid( pid, &status, 0);
      
               printf( "부모: 종료된 자식 프로세스 ID는 %d이며,", pid_child);
               if ( 0 == ( status & 0xff))
               {
                  printf( "정상적으로 종료되었고 반환값은 %d입니다\n", status >> 8);
               }
               else
               {
                  printf( "비 정상으로 종료되었고 종료 시그널 번호는 %d입니다\n", status);
               }
               printf( "이제 제일을 처리하겠습니다.\n");
      
               while( 1 )
               {
                  printf( "부모: %d\n", counter++);
                  sleep( 1);
               }
            }
         }
      }
   }
}
]$ ./a.out
부모: 첫번째 자식 프로세스를 생성합니다.
1st: 저는 첫번째 자식 프로세스로 5까지 카운트하고 종료하겠습니다.
1st: 1
부모: 두번째 자식 프로세스를 생성합니다.
2nd: 저는 두번째 자식 프로세스로 10까지 카운트하고 종료하겠습니다.
2nd: 1
부모: 저는 부모 프로세스로 자식 프로세스 작업이 끝날 때 까지 대기합니다..
1st: 2
2nd: 2
1st: 3
2nd: 3
1st: 4
2nd: 4
1st: 5
2nd: 5
2nd: 6
2nd: 7
2nd: 8
2nd: 9
2nd: 10
부모: 종료된 자식 프로세스 ID는 5845이며,정상적으로 종료되었고 반환값은 99입니다
이제 제일을 처리하겠습니다.
부모: 1
부모: 2
부모: 3
부모: 4
:

이번에는 WNOHANG 옵션을 사용하여 부모 프로세스가 block되지 않고 자식 프로세스의 종료 상태를 확인하는 예제입니다.

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

int main()
{
   int   counter  = 1;
   int   status;
   pid_t pid;
   pid_t pid_child;

   printf( "부모: 첫번째 자식 프로세스를 생성합니다.\n");
   pid   = fork();

   switch( pid)
   {
      case -1  :
      {
         printf( "자식 프로세스 생성 실패\n");
         return -1;
      }
      case 0   :
      {
         printf( "1st: 저는 첫번째 자식 프로세스로 5까지 카운트하고 종료하겠습니다.\n");
         while( 6 > counter )
         {
            printf( "1st: %d\n", counter++);
            sleep( 1);
         }
         return 99;
      }
      default  :
      {
         printf( "부모: 두번째 자식 프로세스를 생성합니다.\n");
         pid   = fork();

         switch( pid)
         {
            case -1  :
            {
               printf( "자식 프로세스 생성 실패\n");
               return -1;
            }
            case 0   :
            {
               printf( "2nd: 저는 두번째 자식 프로세스로 10까지 카운트하고 종료하겠습니다.\n");
               while( 11 > counter )
               {
                  printf( "2nd: %d\n", counter++);
                  sleep( 1);
               }
               return 99;
            }
            default  :
            {
               printf( "부모: 저는 부모 프로세스로 자식 프로세스 작업이 \
종료되었는지 확인하면서 제일을 하겠습니다.\n");

               while( 1 )
               {
                  printf( "부모: %d\n", counter++);
                  pid_child   = waitpid( pid, &status, WNOHANG);
                  if ( 0 != pid_child)
                  {
                     printf( "자식 프로세스가 종료되었습니다.\n");
                  }
                  sleep( 1);
               }
            }
         }
      }
   }
}

]$ ./a.out
부모: 첫번째 자식 프로세스를 생성합니다.
1st: 저는 첫번째 자식 프로세스로 5까지 카운트하고 종료하겠습니다.
1st: 1
부모: 두번째 자식 프로세스를 생성합니다.
2nd: 저는 두번째 자식 프로세스로 10까지 카운트하고 종료하겠습니다.
2nd: 1
부모: 저는 부모 프로세스로 자식 프로세스 작업이 종료되었는지 확인하면서 제일을 하겠습니다.
부모: 1
1st: 2
2nd: 2
부모: 2
1st: 3
2nd: 3
부모: 3
1st: 4
2nd: 4
부모: 4
1st: 5
2nd: 5
부모: 5
2nd: 6
부모: 6
2nd: 7
부모: 7
2nd: 8
부모: 8
2nd: 9
부모: 9
2nd: 10
부모: 10
부모: 11
부모: 12
자식 프로세스가 종료되었습니다.
부모: 13
자식 프로세스가 종료되었습니다.
부모: 14
자식 프로세스가 종료되었습니다.
부모: 15
자식 프로세스가 종료되었습니다.
부모: 16
자식 프로세스가 종료되었습니다.
부모: 17
자식 프로세스가 종료되었습니다.


출처 - http://forum.falinux.com/zbxe/?mid=C_LIB&page=3&document_srl=408548