wait 함수

신준우·2023년 6월 3일
0

시스템 프로그래밍

목록 보기
6/12

이전 내용 복습

완벽한 쉘을 만들기 위해

  • 새로운 프로세스를 만들어내는 fork() 함수
  • 프로그램을 실행하기 위한 execvp() 함수

에 대해서 배웠다

좀 더 완벽한 쉘을 만들기 위해 이번시간에는 wait()함수에 대해 배워볼것이다

wait() 함수

wait함수에 대해 보기 전에, 가져야 할 의문이 있다

Q : Parent 프로세스는 Child프로세스의 종료를 어떻게 기다릴까?
A : wait 함수를 사용해서 child 프로세스가 종료될때까지 기다릴 수 있게 한다!

  • wait 함수에 대해 알아보자
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)

일단 이렇게 생긴 함수다! 하지만 이런것만 봐서는 제대로 함수의 기능과 사용법을 파악하기 어렵다

예제 코드를 통해서 기능과 사용법을 제대로 알아보자!

waitdemo1.c

#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() 함수부터 살펴보자

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를 봐볼까?

child_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를 살펴보자!

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가 출력됨을 알 수 있다

  • 두가지 사실을 확인하고 가자
  1. wait함수는 child 프로세스가 exit()함수를 호출할때까지 parent 프로세스를 막는다

  2. wait함수는 exit()함수를 호출한 child프로세스의 PID값을 반환한다

이 두가지 기능을 한다는걸 기억하자

waitdemo2.c

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 부분밖에 없다,
따로 떼어내서 확인해보자

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);
        //이제 결과값 출력~!
}

갑자기 비트같은 단위들이 나와서 좀 혼란스러울 것이다.

다음시간에 좀 더 자세히 알아보자!

profile
보안

0개의 댓글