티스토리 뷰

fork() 시스템 콜

fork() 함수는 프로세스를 생성하는 함수이다.

fork에 의해 생성되는 프로세스는 자식 프로세스이고, 자식 프로세스는 부모 프로세스의 메모리를 그대로 복사해 사용한다.

그리고 fork이후의 코드부터 각자의 메모리를 사용한다.

 

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc,char * argv[]){
	printf("hello world (pid:%d)\n",(int)getpid());
    int rc = fork();
    if(rc < 0){
    	fprintf(stderr,"fork failed\n");
        exit(0);
    }
    else if(rc == 0){
    	printf("hello, i am child (pid) : %d\n",(int)getpid());
    }
    else{
    	printf("hello, i am parent of %d (pid:%d)",rc,(int)getpid());
    }
   
}

 

 

프로그램이 시작하면서 pid가 13294인 프로세스를 가진다. 다음으로 fork를 호출해 프로세스를 생성한다. 그런데 생성된 프로세스가 pid 13294의 복사본(13945)이 생성되었다. fork에 의해 새로운 자식 프로세스가 생성된 걸 볼 수 있다.

새로 생성된 프로세스는 처음 부터 다시 시작하지 않고 fork이 후 부분부터 시작한다.(hello world가 2번 실행되지 않았다.)

 

부모 프로세스와 자식 프로세스의 차이점은 fork함수의 반환 값이다. 부모 프로세스는 자식 프로세스의 PID를 반환받고 , 자식 프로세스는 0을 반환받는다. 그래서 rc값이 0이면 자식 프로세스가 생성되었다는 메세지가 나온 것이다.

 

wait() 시스템 콜

부모 프로세스가 자식 프로세스의 종료를 대기해야 하는 경우도 있다.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc,char * argv[]){
	printf("hello world (pid:%d)\n",(int)getpid());
    int rc = fork();
    if(rc < 0){
    	fprintf(stderr,"fork failed\n");
        exit(0);
    }
    else if(rc == 0){
    	printf("hell, i am child (pid:%d)\n",(int)getpid());
    }
    else{
		int wc = wait(NULL);
        printf("hello, iam parent of %d (wc:%d) (pid:%d)\n",rc,wc,(int)getpid());
    }
}

부모 프로세스는 wait() 시스템 콜을 호출하여 자식 프로세스 종료 시점까지 자신의 실행을 잠시 중지시킨다. 자식 프로세스가 종료되면 wait()는 리턴된다. 그래서 child가 완료된 후 parent가 호출되고 wait의 값 13555가 반환되었다.

 

부모 프로세스는 자식 프로세스가 종료될 때까지 리턴하지 않는다. 

 

exec() 시스템 콜

이 시스템 콜은 자기 자신이 아닌 다른 프로그램을 실행해야 할 때 사용한다. fork처럼 복사본이 아닌 다른 프로그램을 실행해야 할 때 사용한다.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main(int argc,char * argv[]){
	printf("hello world (pid:%d)\n",(int)getpid());
    int rc = fork();
    if(rc < 0){
    	fprintf(stderr,"fork failed\n");
        exit(0);
    }
    else if(rc == 0){
    	printf("hello, i am child (pid:%d)\n",(int)getpid());
    	char *myargs[3];
        myargs[0] = strdup("wc");
        myargs[1] = strdup("p3.c");
        myargs[2] = NULL;
        execvp(myargs[0],myargs);
        printf("this should`t print out");
    }
    else{
    	int wc = wait(NULL);
        printf("hello, i am parent of %d (wc:%d) (pid:%d)\n",rc,wc,(int)getpid());
    }
}

 

*strdup함수는 인자를 복사하고 인자를 가리키는 포인터를 반환한다.

*wc는 문자열의 개수를 세는 명령어, wc p3.c

 

execvp()함수가 실행된 걸 보여준다.

exec()함수는 새로운 프로세스를 생성해 실행하는게 아니라 현재 실행 중인 프로그램(p3.c)을 다른 실행중인 프로그램(wc)으로 대체하는 것이다. 자식 프로세스가 exec()를 호출한 후에는 p3.c는 전혀 실행되지 않는 것처럼 보인다.wc에 자식 프로세스가 리턴 되었다.

 

왜 이런 API를 사용할까?

쉘을 사용하기 위해서는 fork를 호출하고 exec를 호출하기 전에 코드를 실행할 수 있다. 코드를 실행하면서 프로그램의 환경을 설정하고 다양한 기능을 준비한다.

쉘은 명령어를 실행하기 위해 fork를 호출하여 새로운 자식 프로세스를 만든다. 그런 후 exec()를 호출하여 프로그램을 실행시킨 후 wait()로 부터 리턴하고 다시 프롬프트를 출력하고 다음 명령어를 기다린다.

 

> wc p3.c > newfile.txt

위 명령어는 출력 재지정 명령이다. 자식 프로세스가 생성되고 exec()이 호출되기 전에 표준 출력 파일을 닫고, newfile.txt파일을 연다.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<sys/wait.h>

int main(int argc,char * argv[]){
    int rc = fork();
    if(rc < 0){
    	fprintf(stderr,"fork failed\n");
        exit(0);
    }
    else if(rc == 0){
        close(STDOUT_FILENO);	//표준출력 파일 디스크립터 닫기
        open("./p4.output",O_CREAT|O_WRONLY|O_TRUNC,S_IRWXU);	//p4.output 파일 열기

        char *myargs[3];
        myargs[0] = strdup("wc");
        myargs[1] = strdup("p4.c");
        myargs[2] = NULL;
        execvp(myargs[0],myargs);
    }
    else{
    	int wc = wait(NULL);
    }
}

 

p4를 실행하면, 화면에 아무 일도 일어나지 않는다. 그러나 실제로는 p4는 fork를 호출하여 새로운 자식 프로세스를 생성하고 execvp()를 호출하여 wc프로그램을 실행시킨다. 출력이 p4.output으로 재지정되었기 때문에 화면에는 아무것도 나오지 않는다.

 

숙제

1.

 

2.

 

3.

 

4.

 

5.

 

6.

waitpid에 대해서

https://codetravel.tistory.com/42

 

waitpid 함수 사용하기(wait함수와 비교)

waitpid 함수는 wait 함수처럼 자식 프로세스를 기다릴때 사용하는 함수입니다. 즉, 자식 프로세스의 종료상태를 회수할 때 사용합니다. 하지만 waitpid 함수는 자식 프로세스가 종료될 때 까지 차

codetravel.tistory.com

https://m.blog.naver.com/PostView.nhn?blogId=skout123&logNo=50133478563&proxyReferer=https:%2F%2Fwww.google.com%2F

 

[스카웃 C언어 강좌] 37-2 wait, waitpid 함수

[스카웃 C언어 강좌] 37-2 wait, waitpid 함수 머리말안녕하세요. Programog를 ...

blog.naver.com

 

waitpid(pid_t pid,int *status,int options);

 

첫번째 인자 : 자식 프로세스의 id, -1을 넣으면 부모,자식 프로세스들 중 한가지 임의로 설정됨.

두번째 인자 : 자식 프로세스가 종료될 때의 상태 정보(우리는 NULL을 넣었다.)

세번째 인자 : WNOHANG 옵션은 부모 프로세스가 기다리지 않고 실행, 0을 넣으면 일반 wait처럼 동작.

 

 

 

7.

 

8.

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함