• 카테고리

    질문 & 답변
  • 세부 분야

    시스템

  • 해결 여부

    미해결

vfork시 exit(0)와 return 0의 차이를 잘 모르겠습니다.

19.05.09 17:29 작성 조회수 155

1

1. exec()를 실행할 시에는 vfork가 메모리 복사 측면에서 낫다고 혼자서 공부했습니다. 실제 exec 실행 전에는 메모리를 공유하게 된다고요. 

2. return은 스택에 함수가 남아있다면 계속 그것을 실행하고 만일 main이라면 exit(0)와 동일하게 수행한다

 

그런데 

 

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

 

static int g_var = 1;

char str[] = "PID";

 

int main(int argc, char **argv) {

    int var;

    pid_t pid;

    var = 88;

 

    pid = vfork();

    if(pid < 0) {

        perror("vfork()");

    } 

    else if(pid == 0) {

        g_var++;

        var++;

        printf("Parent %s from Child Process(%d) : %d\n",

                str, getpid(), getppid());

        printf("pid = %d, Global var = %d, var %d\n", getpid(), g_var, var);

        exit(0); // return 0;

    }

    else {

        printf("Child %s from Parent Process(%d) : %d\n", str, getpid(), pid);

    }

 

    printf("pid = %d, Global var = %d, var = %d\n", getpid(), g_var, var);

    return 0;

}

 

왜 exit, return 모두 입출력 flush를 비워주는 것으로 알고 있어 vfork 사용 시 쓰게 되면 오류를 발생하는 것으로 알고 있는데 왜 exit는 오류가 발생하지 않나요?

답변 1

답변을 작성해보세요.

2

vfork()를 호출하게 되면 parent는 child가 종료되거나 exec()될 때까지 멈춰있습니다. child process가 exec()을 하거나 exit()으로 종료하면 parent가 다시 시작됩니다. parent와 child가 메모리를 공유하기 때문에 child가 메모리를 건드리는 일이 없어야 합니다. 함수가 리턴되는 것도 스택의 메모리를 변경하는 것이기 때문에 허용되지 않는 일이 맞습니다. 따라서 명시적으로 exit(0)을 해줘야 정상동작하는 것이 맞습니다. 

main() 함수에서 return 0하는 것은 결국 exit(0)과 같다고 할 수 있는 것도 맞습니다. 따라서 위의 코드에서 main() 함수에서 return 0하는 것도 정상동작해야 할 것 같습니다만, 여기서 조금 다른 부분이 있습니다. main()함수에서 return 0 하는 것이 곧바로 exit(0)으로 치환되지는 않습니다. 실제로 disassemble을 해보시면 main 함수는 그대로 return 0을 수행합니다. exit(0)은 main 함수를 호출한 코드에서 호출하게 되는 것으로 보입니다. 따라서 vfork() 이후 child process에서 return 0으로 종료하게 되면 segment fault가 발생하는 것이 맞는 것 같습니다. 

참고로 한가지 더 말씀드리자면, 리눅스에서 도입한 copy-on-write 기법에 의해 vfork()의 성능 개선은 큰 차이가 없다고 합니다. 책과 문서 여기 저기에서 vfork() 대신 fork()를 사용하는 것을 권장하네요.

도움이 되셨길 바랍니다. :)