Researcher to Developer

프로세스 생성 관련 시스템 콜 - wait() 본문

코딩/Basic

프로세스 생성 관련 시스템 콜 - wait()

Probe29 2021. 1. 2. 16:57
리눅스는 POSIX 호환 운영체제다. 
리눅스는 POSIX에서 정한 시스템콜을 제공하고 있다. 

 

#리눅스 환경에서 프로세스 생성 과정

 

부모 프로세스 안에서 fork () 명령어를 넣고

동일한 데이터와 코드를 가진 별도의 프로세스 공간을 생성하고, (자식 프로세스)

부모/자식 프로세스 각각 fork의 () 함수 다음 줄 code에 Program Counter가 놓여서

리턴 값이 pid 값을 주는데 pid 값을 기반으로

부모/자식 프로세스를 구분 지을 수 있고

조건문을 사용해서 자식 프로세스인 경우에는 exec () 프로그램(시스템 콜)으로 실행 파일을 인자에 넣어서

실행 시키면 해당 코드 이미지로 자식 프로세스가 덮어씌워지고 프로세스가 다시 처음부터 실행하게 되어

덮어씌워진 코드 이미지를 읽어나가게 된다.

 

조건문을 사용해서 부모 프로세스는 wait () 함수를 사용하는데,

리눅스 프로세스 생성 실행 구조에서 자식 프로세스가 끝나기 전에 부모 프로세스가 죽으면 안되기 때문에 사용한다.

자식 프로세스가 어떻게 종료되었는지 상태 정보에 대한 뒷처리 작업을 해주어야 부모 프로세스가 끝나거나

다른 작업을 하는 것이 기본적인 구조이다.

 

그리고 자식 프로세스에서 실행파일을 실행한 다음에는 exit() 를 실행하여 종료한다.
exit () 함수를 통해 부모 프로세스에 SIGCHLD 시그널을 보내준다.

그러면 wait() 함수 다음에 있는 code를 읽어나가게 된다.

 

fork () → exec () → wait () → exit () 

 

 

 

#wait() 시스템 콜

wait() 리턴값
에러가 발생한 경우

#include <sys/wait.h>    // <sys/wait.h> 라이브러리에 선언되어 있음
pid_t wait (int *status)   // 리턴값은 종료된 자식 프로세스의 pid

 

exit 함수와 비교해보면
exit(int status) 는 자식 프로세스가 부르고 status에 종료 상태 값을 번호로 넣어준다.
pid_t wait (int *status) 는 부모 프로세스가 부른다. 여기 status에 해당하는 메모리 공간을 넣어주면  (* =포인터)
OS에서 자식 프로세스 종료 상태 값을 그 메모리 공간에 채워준다.
그 뒤에 코드에서 status 변수의 실제 값을 가지고 자식 프로세스 상태를 부모 프로세스가 알 수 있게 해준다.

status 정보를 통해 기본적인 자식 프로세스 관련 정보를 확인할 수 있다.

ex. 매크로함수
int WIFEXITED(status); // 자식 프로세스가 정상 종료 시 리턴값은 0 이 아닌 값이 됨
0 이면 자식 프로세스가 정상 종료하지 않았다. 는 것을 나타내는 함수

다음은 wait 함수를 실행하는 코드 예제이다.

 

#include <sys/types.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
int main() {
      int pid;
      int child_pid;      // 3 개의 변수 선언
      int status;
      pid = fork();
      switch (pid) {
           case -1:               
                perror("fork is failed\n");
                break;
           case 0:
                execl("/bin/ls", "ls", "-al", NULL);
                perror("execl is failed\n");                   //execl 이 실패할 경우 출력될 에러
                break;
           dafault:
                child_pid = wait(&status);                    //wait() 함수 실행, 자식 프로세스 끝날 때까지 기다림
                if (WIFEXITED(status)) {
                        printf("Child process is normally terminated\n");
                }
                exit(0);
     }
}

 

pid 값이 -1 이면 error를 나타냄
perror는 에러 메세지를 출력하고 종료하는 함수
pid 값이 0 이면 자식 프로세스에서 'ls -al'함수를 실행한다.
default 는 부모 프로세스 pid 숫자가 나올 것
child_pid = wait(&status); status가 포인터 변수로 선언된 것이 아니라서 &문자를 써서 포인터변수로 바꿔줬음