본문 바로가기
Linux

[Linux] fork, exec 함수의 차이점을 알아보자

by snwo 2021. 10. 3.

리눅스에는 execl, execlp, execle, execv, execvp, execvpe 처럼 exec 계열의 함수가 있다.

인자 전달하는거 따라서 이름이 조금씩 변한다.

https://man7.org/linux/man-pages/man3/exec.3.html

자세한건 찾아보도록하자

 

현재 프로세스 이미지를 인자로 준 바이너리 이미지로 대체한다.

포너블 문제를 풀 때, gdb 를 붙여서 디버깅 하는데,

system("/bin/sh") 이런걸 실행했을 때, gdb 에서 더이상 디버깅이 안되는 경우가 있는데,

system 함수 내부에서 execve 를 실행하므로 현재프로세스가 /bin/sh 로 대체되기 때문이다.

 

fork 함수는 이와 다르게, 새 프로세스를 복제해서 생성한다.

분리된 메모리공간을 새로 할당받지만, 생성되었을 때 메모리는 같은 내용을 담고있다.

caller : 부모

callee : 자식

 

근데 자식프로세스에서도 또다른 자식프로세스를 생성할 수 있다.

 

fork 함수 리턴값 

+ 성공 : 자식 PID

+ 실패 : -1

+ fork 실행으로 생성된 자식프로세스 : 0

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

int main() {
    int x;
    x = 55;
    int d=fork();
    printf("PID : %ld,  x : %d, d : %d\n",getpid(), x,d);
    x = 100;
    d=fork();
    printf("PID : %ld,  x : %d, d : %d\n",getpid(), x,d);
    return 0;
}

자식 프로세스를 두 개 생성하는 간단한 예제입니다.

첫 번째 fork 실행으로, 자식프로세스가 생성됩니다.

 

자식프로세스가 생성될 때, 자식프로세스에서도 동일하게 int d = fork(); 문부터 시작합니다.

하지만, 이 부분은 자식프로세스가 생성된 부분이기때문에 fork 함수에서는 0을 반환하게 됩니다.

 

이 특징으로, 

if(!fork()){

// 자식

}

else {

// 부모 or error

}

이렇게 부모/자식 프로세스에서 처리해야할 일을 나눌 수 있습니다.

 

밑에도 동일하게 처리되는데, 그림을 그려 flow 를 파악해봅시다.

부모프로세스인 949 는 950 / 951 을 생성합니다.

x=100 은 중간에 있으니, 950 을 x=55 를 복사해서 갖고, 951 은 x=100 을 복사해서 갖게됩니다.

 

950 에서도 fork 가 두 번 실행되어, 0 / 952 를 리턴받는데, 0 출력할 때는 x=55 를 출력하고,

x=100 설정,  952 프로세스에서는 x=100 을 복사해 갖게되고 fork 함수 한 번 실행되어 0 리턴받고 출력

 

951 에서는 x=100 을 복사해서 가졌고, fork 함수가 한 번 실행되어 0 리턴받고 출력

 

핵심은, 자식프로세스가 실행된 fork 에서는 0이 리턴되고, 다른 fork 를 만나면 또다른 자식프로세스를 생성한다는 점이다.

 

만약 fork 가 3 번 실행된다면 총 몇개가 생성될까요?

수학을 못해서 여기까지하겠습니다.