완벽한 쉘을 만들기 위해
에 대해서 배웠다
wait함수에 대해 보기 전에, 가져야 할 의문이 있다
Q : Parent 프로세스는 Child프로세스의 종료를 어떻게 기다릴까?
A : wait 함수를 사용해서 child 프로세스가 종료될때까지 기다릴 수 있게 한다!
wait |
---|
PURPOSE 프로세스의 종료를 기다린다 |
INCLUDE #include <sys/types.h>, #include <sys/wait.h> |
USAGE pid_t result = wait(int *statusptr) |
ARGS statusptr: child result |
RETURNS -1:if error, pid: of terminated process |
SEE ALSO waitpid(2), wait3(2) |
일단 이렇게 생긴 함수다! 하지만 이런것만 봐서는 제대로 함수의 기능과 사용법을 파악하기 어렵다
예제 코드를 통해서 기능과 사용법을 제대로 알아보자!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define DELAY 2
void child_code(int delay){
printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
sleep(delay);
printf("child done. about to exit\n");
exit(17);
}
void parent_code(int childpid){
int wait_rv;
wait_rv = wait(NULL);
printf("done wating for %d. Wait returned: %d\n", childpid, wait_rv);
}
int main(int argc, char* argv[]){
int newpid;
void child_node(), parent_node();
printf("before: mypid is %d\n", getpid());
if((newpid = fork()) == -1){
perror("fork");
}
else if(newpid == 0){
child_code(DELAY);
}
else{
parent_code(newpid);
}
}
자, 이렇게 예제 코드가 주어졌다
한번 main() 함수부터 살펴보자
int main(int argc, char* argv[]){
int newpid; //int형 변수 newpid선언
void child_code(), parent_code(); //함수의 프로토타입 선언
printf("before: mypid is %d\n", getpid()); //현재 프로세스의 id를 getpid함수를 사용해 출력
if((newpid = fork()) == -1){ //만약 fork함수의 값이 -1이라면, 즉 fork에서 오류가 생기면
perror("fork"); //오류 메세지 출력
}
else if(newpid == 0){ //newpid값이 0이라면? == child process가 실행되고있다면
child_code(DELAY); //child_code 함수 실행!
}
else{ //나머지 경우, 즉 오류가 나지도 않고, child process가 실행되는것도 아닌 경우
parent_code(newpid); //parent_code 함수 실행!
}
}
뭐, 기본적으로 main함수에서는 wait함수는 쓰이지 않았다.
단순히 에러함수 출력, child_code와 parent_code 실행하기 위한 함수이다
그럼 각각의 if else 부분에서 보이는 child_code 와 parent_code를 봐볼까?
void child_code(int delay){ //delay라는 int형 변수를 매개변수로 가짐
printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
// child process에서 실행되는 부분, 현재 child프로세스의 id와 delay값 출력
sleep(delay); //delay 시간만큼 프로세스 일시정지
printf("child done. about to exit\n"); //child프로세스가 종료됨을 출력
exit(17); // child 프로세스 종료, 자식 프로세스가 종료되었을때 17을 반환한다는 뜻
}
이것 또한 단순히 child process의 id와 delay값을 출력해주고, child process의 종료를 보>여주는 함수일 뿐이다
그럼 이제 parent_code를 살펴보자!
void parent_code(int childpid){ //childpid라는 int형 매개변수를 가짐
int wait_rv; //wait_rv라는 int형 변수를 선언
wait_rv = wait(NULL); //wait함수에 NULL 값을 전달, 즉 자식 프로세스의 종료를 기다리게한다
//wait_rv값에 종료된 자식프로세스의 id를 전달
printf("done wating for %d. Wait returned: %d\n", childpid, wait_rv);
// 그 값을 출력한다!
}
사실상 이 parent_code가 중요하다!
wait 함수는 자식 프로세스가 끝날때까지 기다리게 하는 함수임을 확인할 수 있다
결과 실행 화면도 함께 확인하면서 마무리해보자
현재 pid와 child pid가 출력됨을 알 수 있다
wait함수는 child 프로세스가 exit()함수를 호출할때까지 parent 프로세스를 막는다
wait함수는 exit()함수를 호출한 child프로세스의 PID값을 반환한다
이 두가지 기능을 한다는걸 기억하자
wait함수는 parent에게 child가 어떻게 종료됐는지 전달해준다
이 기능을 확인하기 위해 두번째 예제 코드를 봐보자!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define DELAY 2
void child_code(int delay){
printf("child %d here. will sleep for %d seconds\n", getpid(), delay);
sleep(delay);
printf("child done. about to exit\n");
exit(17);
}
void parent_code(int childpid){
int wait_rv;
int child_status;
int high_8, low_7, bit_7;
wait_rv = wait(&child_status);
printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
high_8 = child_status >> 8;
low_7 = child_status & 0x7f;
bit_7 = child_status & 0x80;
printf("status: exit = %d, sig = %d, core = %d\n", high_8, low_7, bit_7);
}
int main(int argc, char* argv[]){
int newpid;
void child_node(), parent_node();
printf("before: mypid is %d\n", getpid());
if((newpid = fork()) == -1){
perror("fork");
}
else if(newpid == 0){
child_code(DELAY);
}
else{
parent_code(newpid);
}
}
이 코드에서 사실상 바뀐건 parent_code 부분밖에 없다,
따로 떼어내서 확인해보자
void parent_code(int childpid){ //childpid값을 매개변수로 받는 함수
int wait_rv; //wait_rv라는 int형 변수를 선언 이름을 보아하니 wait함수와 관련
int child_status; //child_status라는 int형 변수 선언, 이름을 보았을때 child process의 상태?
int high_8, low_7, bit_7; //high, low, bit라는 변수 선언
wait_rv = wait(&child_status); //child프로세스의 종료 상태를 wait함수를 사용해서 기다림
printf("done waiting for %d. Wait returned: %d\n", childpid, wait_rv);
// child process이 종료됐음을 출력, wait함수의 반환값 출력
high_8 = child_status >> 8; // child status의 변수값을 8비트 이동하여 high_8에 저장
low_7 = child_status & 0x7f; //child status와 0x7f(01111111)를 비트단위의 AND연산을 하여 저장
// child프로세스가 종료될때 반환하는 상태 정보 중 하위 7비트인
// 시그널 추출
bit_7 = child_status & 0x80; //child status와 0x80(10000000)를 비트단위의 AND연산을 하여 저장
// 7번째 비트인 코어 덤프 여부 추출
printf("status: exit = %d, sig = %d, core = %d\n", high_8, low_7, bit_7);
//이제 결과값 출력~!
}
갑자기 비트같은 단위들이 나와서 좀 혼란스러울 것이다.
다음시간에 좀 더 자세히 알아보자!