[운영체제] fork() 함수란? , fork() 함수 예제 , 부모 자식 프로세스

fork() 함수란?

Unix 환경에서 fork() 함수는 함수를 호출한 프로세스를 복사하는 기능을 한다. 이때 부모 프로세스와 자식 프로세스가 나뉘어 실행되는데, 원래 진행되던 프로세스는 부모 프로세스(parent), 복사된 프로세스를 자식 프로세스(child) 라고 한다.

 

fork() 함수는 프로세스 id, 즉 pid 를 반환하게 되는데 이때 부모 프로세스에서는 자식 pid가 반환되고 자식 프로세스에서는 0이 반환된다. 만약 fork() 함수 실행이 실패하면 -1을 반환한다. 

 

프로세스에 대해 잘 모르겠다면 다음을 참고하자.

 

[운영체제] 프로세스란? 프로세스 메모리 구조, 상태, 스케줄링

프로세스(Process)란? 프로세스는 실행 중인 프로그램(program)을 뜻한다. 그렇다면 프로그램은 무엇인가? 프로그램은 명령어들의 모음을 포함한 디스크에 저장된 파일이다. 프로그램이 실행되면 이

code-lab1.tistory.com

 

fork() 함수는 COW(Copy On Write)를 사용하기 때문에 자식 프로세스와 부모 프로세스가 독립적으로 변수를 사용할 수 있다.

 

 

 

[운영체제] Copy On Write(COW)란? | Copy On Write 예시

Copy On Write (COW) 란? 1 2 3 4 5 6 std::string x("Hello"); std::string y = x; // x and y use the same buffer y += " World!"; // now y uses a different buffer // x still uses the same old buffer cs 위와 같은 코드가 있다고 하자. ( C++ 98에서

code-lab1.tistory.com

 

 

 

fork() 함수 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    
    pid_t pid;
    int x = 1;
 
    pid = fork();
    if(pid == 0){ /*Child*/
        printf("child: x=%d\n"++x);
        exit(0);
    }
 
    /*Parent*/
    printf("parent: x=%d\n"--x);
    exit(0);
}
cs

 

위와 같은 코드를 실행하면 어떤 결과가 나올까? fork() 함수가 실행된 순간 프로세스가 하나 복사되고 이후 아래 코드들이 실행될 것이다. 

 

fork() 1

 

위에서 자식 프로세스는 fork() 함수의 반환값이 0이라고 했다. 따라서 pid 가 0일 때는(child) x가 1증가해 "child: x=2" 가 출력된다.

 

반면 부모 프로세스는 pid가 자식의 프로세스 id를 가질 것이다. 따라서 "parent: x=0" 이 출력된다.

 

result1
실행결과

 

참고로 부모와 자식 프로세스 중 어떤것이 먼저 실행될지는 알 수 없다. 따라서

child: x=2
parent: x=0

순으로 출력될 수 도 있다.

 

몇가지 더 실험해보자.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    
    printf("L0\n");
    fork();
    printf("L1\n");
    fork();
    printf("Bye\n");
}
cs

 

위와 같은 코드는 어떻게 동작할까?? 그림으로 보면 간단하게 이해할 수 있다.

 

 

fork() 2
fork() 실행 예시 2

 

그림을 보면, fork() 를 할 때마다 자식 프로세스가 생기는 것을 확인 할 수 있다. 

result2
실행결과

 

결과는 위와 같이 나올 수도 있고, 다른 결과가 나올 수도 있다.

result3
실행결과

 

어떤 프로세스가 먼저 실행될 지 알 수 없기 때문에, 위와 같은 순서대로 결과가 나오기도 한다.

 

이때 결과로 나올수 있는 것을 Feasible output, 결과로 나올수 없는 것을 Infeasible output이라고한다. 

예를 들어 아래와 같다. 그림을 잘 보면서 이해해보자.

Feasible output                Infeasible output
L0                                 L0
L1                                 Bye <- 불가능
Bye                               L1
Bye                               Bye
L1                                 L1
Bye                               Bye
Bye                               Bye

 

다음 예제도 봐보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    
    printf("L0\n");
    if(fork() != 0){
        printf("L1\n");
        if(fork() != 0){
            printf("L2\n");
        }
    }
    printf("Bye\n");
}
cs

 

역시 그림으로 이해해보자.

fork() 3

 

result5
실행결과

 

fork() 반환 결과가 0이라면 자식이고 0이 아니면(자식프로세스의 id를 가질것) 부모 프로세스이다. 따라서 if(fork() != 0)아래 코드는 부모 프로세스에서만 실행되는 것이다. 실행결과는 마찬가지로 다양한 결과가 나올 수 있다. 여기서도 Infeasible output을 생각해보면 좋을 것이다.

 

다음 예제도 봐보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(){
    
    printf("L0\n");
    if(fork() == 0){
        printf("L1\n");
        if(fork() == 0){
            printf("L2\n");
        }
    }
    printf("Bye\n");
}
cs

 

역시 그림으로 이해해보자.

 

fork() 실행예시

 

result6
실행결과

 

fork() 반환값이 0이라면 자식프로세스라는 것이다. 즉 if(fork()==0) 아래 코드는 자식프로세스에서만 실행되는 것이다!

마찬가지로 가능한 출력결과와 불가능한 출력결과를 생각해보자. 

 

반응형

댓글

Designed by JB FACTORY