2014년 1월 29일 수요일

[리눅스 시스템 프로그래밍] fork() ,exec 시스템 콜의 의미(Meaning of fork() and exec system call)

리눅스 커널 공부를 1년 전 쯤에 했다.  fork(), exec 함수군에 대해서 읽어 봤지만 이건 당최 무슨 소리인지 알 수가 없었다. 요즘「리눅스 시스템 프로그래밍(로버트러브 저)」을 읽으니까 이 함수들이 어떤 역할을 하는지 대충 알 것 같다.
시스템 프로그래밍(여기서 의미하는 것은 시스템 콜)을 먼저 공부하고 커널 공부를 했더라면... 하는 생각이 든다. 커널을 공부하기 위해서는 시스템 콜을 어느정도 알고있어야 된다고 생각한다.

1. fork() 시스템 콜은 현재 프로세스와 동일한 이미지로 동작하는 새로운 프로세스를 만든다.
(A new process running the same image as the current one can be created via the fork()
system call)
2. exec 함수군(execl(), execlp(), execle(), execv(), execvp(), execve())을 호출하면 path가 가리키는 프로그램을 메모리에 올리는 방법으로 현재 프로세스 이미지를 새로운 프로세스 이미지로 대체한다.
(A call to execl() replaces the current process image with a new one by loading into
memory the program pointed at by path)

"쓰기 후 복사(COW:copy-on-write)는 fork의 경우 더욱 큰 장점을 제공한다. fork 다음에 exec가 뒤따를 확률이 아주 높으므로 부모 주소 공간을 자식 주소 공간으로 복사하는 행위는 종종 완전한 시간 낭비다. 자식이 즉시 새로운 바이너리 이미지를 실행한다면 이전 주소 공간은 완전히 제거된다. COW는 이런 경우를 위해 최적화를 수행한다."

(Copy-on-write has yet a bigger benefit in the case of forking. Because a large percentage of forks are followed by an exec, copying the parent’s address space into the child’s address space is often a complete waste of time: if the child summarily executes a new binary image, its previous address space is wiped out. Copy-on-write optimizes for this case.)

다음은 fork 다음에 exec가 뒤따르는 코드이다.
(code that fork is followed by an exec)

_________________________________________________________________________________
1  pid_t pid;
2  
3  pid = fork();
4  if (pid == -1)
5   perror ("fork");
6  
7  /* 자식 프로세스 */ /* child process */
8  if (!pid) {
9   const char *args[] = { "windlass", NULL };
10 int ret;
11
12    ret = execv ("/bin/windlass", args);
13 if (ret == -1) {
14 perror ("execv");
15 exit (EXIT_FAILURE);
16 }
17 }
_________________________________________________________________________________

자식 프로세스에서는 fork() 호출이 성공하면 0을 반환한다. 부모 프로세스에서 fork()는 자식 프로세스의 pid를 돌려준다. line 8에서 pid가 0인 것을 검사하고 자식 프로세스의 코드를 실행하는데 자식 프로세스는 0을 반환하기 때문이다.
새로운 자식을 얻었다는 사실을 제외하고는 부모 프로세스는 변함없이 계속해서 돌아간다.  execv()호출은 자식이 /bin/windlass 프로그램을 실행하도록 변경한다.

댓글 없음:

댓글 쓰기