waitpid 함수는 wait 함수처럼 자식 프로세스를 기다릴때 사용하는 함수입니다. 즉, 자식 프로세스의 종료상태를 회수할 때 사용합니다.
하지만 waitpid 함수는 자식 프로세스가 종료될 때 까지 차단되는 것을 원하지 않을 경우, 옵션을 사용하여 차단을 방지할 수 있습니다.
그리고 기다릴 자식 프로세스를 좀더 상세히 지정할 수 있습니다.
#include <sys/wait.h> pid_t waitpid(pid_t pid, int *statloc , int options); 성공 : 프로세스 ID 반환 오류 : -1 |
waitpid 함수의 첫번째 인자에 대해서 알아 보겠습니다.
wiatpid 함수의 첫 번째 인자 |
의미 |
pid가 -1 일 경우 (pid == -1) |
임의의 자식 프로세스를 기다림 |
pid가 0 보다 클 경우 (pid > 0) |
프로세스 ID가 pid인 자식 프로세스를 기다림 |
pid가 -1 보다 작을 경우 (pid < -1) |
프로세스 그룹 ID가 pid의 절댓값과 같은 자식 프로세스를 기다림 |
pid가 0일 경우 (pid == 0) |
waitpid를 호출한 프로세스의 프로세스 그룹 PID와 같은 프로세스 그룹 ID를 가진 프로세스를 기다림 |
waitpid 함수의 오류(-1)는 지정한 pid의 프로세스 또는 프로세스 그룹이 없는 경우에 발생하며 그리고 pid가 자식 프로세스가 아닐 때 발생합니다.
두번째 인자에 대해서 알아 보겠습니다.
| waitpid 함수 반환 값 | 두 번째 인자 인 statloc 값 |
자식 프로세스가 정상적으로 종료 | 프로세스 ID | - WIFEXITED(statloc) 매크로가 true를 반환 - 하위 8비트를 참조하여 자식 프로세스가 exit, _exit, _Exit에 넘겨준 인자값을 얻을 수 있음, WEXITSTATUS(statloc) |
자식 프로세스가 비정상적으로 종료 | 프로세스 ID | - WIFSIGNALED(statloc) 매크로가 true를 반환 - 비정상 종료 이유를 WTERMSIG(statloc) 매크로를 사용하여 구할 수 있음 |
waitpid 함수 오류 | -1 | - ECHILD : 호출자의 자식 프로세스가 없는 경우 - EINTR : 시스템 콜이 인터럽트 되었을 때 |
세번째 인자에 대해서 알아 보겠습니다.
세 번째 인자로 사용가능한 상수 |
의미 |
WCONTINUED |
중단 되었다가 재개된 자식 프로세스의 상태를 받음 |
WNOHANG |
기다리는 PID가 종료되지 않아서 즉시 종료 상태를 회수 할 수 없는 상황에서 호출자는 차단되지 않고 반환값으로 0을 받음 |
WUNTRACED |
중단된 자식 프로세스의 상태를 받음 |
아래 예제는 세 번째 인자에 아무것도 주지 않았을 때 wait 함수와 동일한 동작하는 것을 확인해 보겠습니다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t childPid; int status; childPid = fork(); if(childPid > 0) { // 부모 프로세스 int ret; printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid); sleep(3); ret = waitpid(childPid,&status,0); // 세번째 인자에 0을 넣었으므로 wait 함수와 동일한 동작을 함 printf("부모 종료 %d %d %d\n",ret,WIFEXITED(status),WEXITSTATUS(status)); exit(0); } else if(childPid == 0){ // 자식 코드 printf("자식 시작 PID : %ld\n", (long)getpid()); sleep(8); printf("자식 종료\n"); exit(0); } else { // fork 실패 perror("fork Fail! \n"); return -1; } return 0; }
실행 결과를 보겠습니다.
부모 PID : 13444, pid : 13445 자식 시작 PID : 13445 자식 종료 부모 종료 13445 1 0 |
부모 프로세스는 3초 동안 동작하고 자식 프로세스는 8초 동안 동작하는 예제 코드입니다. 하지만 결과는 자식 프로세스가 먼저 종료되고 부모 프로세스가 종료되었습니다.
waitpid 함수는 세번째 인자로 0을 주었기 때문에 자식 프로세스가 종료될 때 까지 blocking 되었기 때문입니다.
WIFEXITED 매크로는 1(true)를 리턴하였으며 WEXITSTATUS는 자식 프로세스가 0을 리턴 한 것을 알려주고 있습니다.
다음 예제는 세 번째 인자에 WNOHANG 옵션을 넣어보도록 하겠습니다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t childPid; int status; childPid = fork(); if(childPid > 0) { // 부모 프로세스 int ret; printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid); sleep(3); ret = waitpid(childPid,&status,WNOHANG); // WNOHANG 옵션을 사용하면 자식 프로세스가 종료되지 않았을 경우 blocking 되지 않고 즉시 0값을 리턴합니다. printf("부모 종료 %d %d\n",ret,WIFEXITED(status)); exit(0); } else if(childPid == 0){ // 자식 코드 printf("자식 시작 PID : %ld\n", (long)getpid()); sleep(8); printf("자식 종료\n"); exit(0); } else { // fork 실패 perror("fork Fail! \n"); return -1; } return 0; }
실행 결과를 확인해 보겠습니다.
부모 PID : 14289, pid : 14290 자식 시작 PID : 14290 부모 종료 0 0 127 자식 종료 |
waitpid 함수는 0을 리턴하였으며 WIFEXITED 매크로도 false를 리턴하였습니다. WNOHANG 옵션을 사용하였기 때문에 자식 프로세스가 종료될 때 까지 기다리지 않고 waitpid 함수가 바로 0값을 리턴하였기 때문입니다.
마지막으로 존재하지 않는 자식 프로세스의 PID를 waitpid 첫 번째 인자로 넣어 보겠습니다.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/error.h> #include <sys/string.h> int main() { pid_t childPid; int status; childPid = fork(); if(childPid > 0) { // 부모 프로세스 int ret; printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid); sleep(3); ret = waitpid(99999,&status,WNOHANG); // pid로 99999(존재하지 않는 프로세스 ID) printf("부모 종료 %d %d %s\n",ret,errno,strerror(errno)); // 오류가 발생하였을 경우 errno값을 확인 exit(0); } else if(childPid == 0){ // 자식 코드 printf("자식 시작 PID : %ld\n", (long)getpid()); sleep(8); printf("자식 종료\n"); exit(0); } else { // fork 실패 perror("fork Fail! \n"); return -1; } return 0; }
실행 결과를 보도록 하겠습니다.
부모 PID : 17859, pid : 17860 자식 시작 PID : 17860 부모 종료 -1 10 No child processes 자식 종료 |
waitpid 함수는 -1 오류 값을 반환하였습니다. 그리고 에러 넘버(errno) 10, 즉 NO child processes라는 에러를 출력하였습니다.
99999라는 자식 프로세스가 존재하지 않는다는 의미입니다. 그 이유는 waitpid 함수의 첫 번째 인자로 존재하지 않는 99999 PID값을 입력하였기 때문입니다.
지금까지 wait 함수보다 좀더 다양한 기능을 제공하는 waitpid 함수에 대해서 알아 보았습니다.
'Language > C | C++' 카테고리의 다른 글
좀비 프로세스와 고아 프로세스(Zombie process and Orphan process) (0) | 2018.02.07 |
---|---|
wait 함수 사용하여 자식 프로세스 종료시까지 대기하기 (1) | 2018.02.05 |
exit 함수를 사용하여 프로세스 종료하기 (0) | 2018.02.04 |
fork 함수 사용하여 프로세스 생성 (7) | 2018.01.21 |