프로세스를 새로 생성할때 fork 함수를 이용할 수 있습니다.
fork 함수를 호출한 프로세스는 부모 프로세스가 되고
새롭게 생성되는 프로세스는 자식 프로세스가 됩니다.
두 프로세스는 다른 pid를 가지고 독립적이게 동작합니다.
Copy On Write
이때 Linux에서는 자식 프로세스를 생성하면 같은 메모리 공간을 공유하게 됩니다.
부모 프로세스에서 페이지 바로 C를 수정한다면 자식 프로세스에도 영향을 끼칠것입니다.
그래서 직접 변경 대신 페이지 C를 복사해서 수정(Copy on write)하는 방식으로 작동합니다.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
int statofLoc; // get child process's state when child process is done
int childPid;
char **command; //get parsed words, command[0] is command,
//others option
void fatal_error(char* errorCommand) // to record error and exit
{
perror(errorCommand);
exit(-1);
}
childPid = fork();
if(childPid == 0){ // child
if(execvp(command[0], command)<0)
{
fatal_error("unknown command");
//if this function is actived,
//something is wrong
}
}
else if(childPid < 0) //error
{
fatal_error("pid ERROR");
}
else //parent
{
waitpid(childPid, &statofLoc, WUNTRACED);
//wait till child process is done.
}
wait(혹은 waitpid) 함수를 이용하면 부모 프로세스는 자식 프로세스가 종료될때까지 기다릴 수 있습니다.
wait는 다음과 같이 작동합니다.
1. 자식 프로세스가 동작 중이면 호출 차단이 차단되기 때문에 상태를 얻어올 때까지 대기
2. wait() 함수 호출자가 시그널을 받을 때까지 대기
3. 자식 프로세스가 종료된 상태라면 즉시 호출이 반환되어 상태를 얻음, 이 때 wait() 함수는 자식 프로세스의 프로세스 ID를 반환
4. 자식 프로세스가 없다면 호출이 즉시 반환되며, 에러값을 반환
고아 프로세스
부모가 먼저 자식 프로세스보다 먼저 종료되면 자식 프로세스는 고아 프로세스가 됩니다.
만약 부모가 먼저 종료되면 커널은 부모 프로세스가 누구의 부모인지 확인하고 자식 프로세스들의 부모 프로세스 ID
(ppid)들을 전부 1(init process)로 바꿔줍니다.
리눅스에서 백그라운드에서 돌아가는 데몬 프로세스를 생성하는 방법으로 해당 방식을 이용합니다.
1. fork후 부모 종료(ppid 가 1로 변경)
2. setsid로 고아 프로세스를 세션 리더로 생성
3. etc...
고아 프로세스가 종료되면 init process가 wait를 호출해 좀비 프로세스가 되는것을 방지합니다.
좀비 프로세스
자식 프로세스가 종료되었지만 자식 프로세스의 종료상태를 회수하지 않았을때 자식 프로세스를 좀비 프로세스라 합니다.
자식 프로세스가 exit 시스템콜을 호출하면 프로세스에 대한 메모리 & 리소스가 해제되 다른 프로세스에서 사용 가능합니다.
그런데 자식 프로세스의 정보를 알고 싶어할 수 있기 때문에 부모 프로세스의 wait system call 호출 이전까지는 최소한의 정보를 가지는 상태로 남아 있습니다.
wait로 정말로 제거되기 이전 상태를 좀비 프로세스라고 부릅니다.
그럼 fork를 어디에 쓰나요..? 보통 멀티테스킹을 위해 많이 쓰입니다.
대표적인 예시로는 shell에서
터미널에서 fork 해 자식 프로세스를 만든 다음
자식 프로세스에서 명령어를 파싱하고, exec system call을 해 명령을 처리합니다.
다만 cd(change directory)의 경우 자식 프로세스가 아니라 부모 프로세스(터미널) 자체가 움직여야 하기 때문에
cd는 예외적으로 fork를 하지않고 직접 처리합니다.
reference
COW
https://openwiki.kr/tech/copy-on-write
https://codetravel.tistory.com/30?category=993122
데몬 프로세스
https://kukuta.tistory.com/386