waitpid_wait
# waitpid와 wait : 자식 프로세스의 종료
waitpid와 wait은 일반적으로 생성된 자식 프로세스가 종료하거나 멈추도록 기다리거나, 그러한 상황인지를 판단하는데 사용할 수 있는 함수들이다. 우선 waitpid의
함수 원형은 다음과 같다.
pid_t waitpid( pid_t pid, int* status_ptr, int options );
waitpid 함수는 프로세스 ID가 pid인 프로세스의 상태정보를 얻어오는데 주로 사용된다. 각각의 인수들은 이름을 보면 어떠한 것을 의미하는지 대략 짐작 가능할 것이
다.
- pid : 상태를 알아보고자 하는 프로세스의 ID이다. -1 이나 WAIT_ANY로 설정하면 어떤 자식 프로세스든 하나만 종료하기를 기다리겠다는것을 뜻하고(즉, wait 함수
와 같은 방식으로 동작하게 된다), 0 이나 WAIT_MYPGRP는 호출된 프로세스와 같은 그룹에 있는 어떤 자식프로세스든 하나만 종료하기를 기다리겠다는것을 뜻한다. 그리
고 음수값이라면 그 절대값의 그룹 ID 내의 자식 프로세스를 위한 정보를 요청하게 된다.
- options : 비트마스크이다. 0과 다음 두 값들의 OR로 구성한다.
WNOHANG : 어떤 자식이 종료되지 않았더라도 함수는 바로 리턴된다.
WUNTRACED : 종료된 프로세스 뿐만 아니라 멈춘 프로세스로부터도 상태정보를 얻어온다.
- status : 프로세스의 상태를 얻어오는데 필요하다. NULL이 아니라면 여기에 프로세스의 상태가 저장이 되는데 다음의 매크로들로 알 수 있다.
WIFEXITED( status ) : 정상적으로 종료되었다면 non-zero이다.
WEXITSTATUS( status ) : return 값이 설정되고 종료된 프로세스 리턴값의 최하 8비트를 평가한다.
WIFSIGNALED( status ) : 자식 프로세스가 어떤 시그널에 의해 종료되었다면 TRUE 값을 반환한다.
WTERMSIG( status ) : 자식 프로세스가 시그널에 의해 종료된 경우, 시그널 번호를 반환한다.
WIFSTOPPED( status ) : 자식 프로세스가 현재 정지된 상태라면 TRUE를 반환한다.
WSTOPSIG( status ) : 자식 프로세스가 정지된 상태가 되도록 한 시그널 번호를 반환한다.
리턴값은 에러라면 -1, WNOHANG이 사용되고 어떤 자식도 이용되지 않았다면 0, 그 이외의 정상적인 경우는 보고된 상황을 가진 자식 프로세스의 PID이다.
에러가 발생했을 때 errno 값은 다음과 같은 것들이 있다.
- EINTR : 시그널에 의해 인터럽트 됨
- ECHILD : pid로 지정된 프로세스가 존재하지 않거나 호출한 프로세스의 자식이 아님
- EINVAL : options 값이 유효하지 않음
- ERESTARTSYS : WNHANG이 설정되지 않았는데 시그널이 잡혔을 때
- ENOBUFS : 버퍼가 부족할 때
wait 함수는 앞에서 이미 언급했다시피 waitpid의 pid_t 인자가 -1일때와 동일하게 동작한다. wait(&status)는 waitpid(-1, &status, 0)와 완전히 동일하다.
다음은 waitpid의 사용예이다. 기다림이 없이, 종료된 모든 자식 프로세스에게서 보내온 그들의 상태를 얻는다.
void sigchild_handler( int signum ) {
pid_t pid;
int status;
int child_val;
/*** 특정OS에서는 세팅을 해줘야처리가 됨. Set up handler again. ***/
/*** (void) signal( SIGCHLD, sigchild_handler ); ***/
while(1) {
pid = waitpid( -1, &status, WNOHANG );
if( pid == 0 ) { /* none left */
break;
}
if ( pid < 0 ) {
/*
* calling standard I/O functions like fprintf() in a signal handler is not recommended, but probably OK in simple programs like this one.
*/
if ( errno == EINTR || errno == EAGAIN ) {
continue;
}
/* ECHILD shouldn't happen with the WNOHANG option, but with some kernels it does anyway. Ignore it. */
if ( errno != ECHILD )
{
fprintf(stdout, "child waitpid errno[%d][%s]", errno, strerror(errno) ); fflush(stdout);
}
break;
}
/*
* We now have the info in 'status' and can manipulate it using the macros in wait.h
*/
if (WIFEXITED(status)) /* did child exit normally? */
{
child_val = WEXITSTATUS(status); /* get child's exit status */
fprintf(stderr, "child's exited normally with status %d\n", child_val);
}
}
}
waitpid와 wait은 sys/wait.h에 있다.