Computer Science/운영체제

[운영체제] 9. 시스템 콜의 종류 - fork() , exec(), wait(), exit()

minjiwoo 2023. 6. 25. 13:56
728x90

시스템 콜의 종류 4가지에 대해 알아본다. 프로세스 생성, 실행, 종료와 관련된 주요 4가지 시스템 콜은 다음과 같다. 

  • fork() : 복제본 child process를 생성한다. 
  • exec() : 새로운 프로그램으로 overlay 한다. 
  • wait() : child process 작업이 끝날 때까지 sleep 한다. 
  • exit() : 모든 resource들을 free 시키고, parent node에게 이를 알린다. 

 

fork() 시스템 콜 

process는 fork() 시스템 콜에 의해 생성된다. caller 를 복사해서 새로운 주소 공간을 생성한다. 

fork() 를 통해서 프로세스를 생성하는 예시이다. 

int main() 
{
	int pid;
    printf("Only parent process print this sentence\n");
    pid = fork();
    if (pid == 0)
    	printf("I am child!\n");
    else if (pid > 0)
    	printf("I am parent!\n");
}

fork() 시스템 콜 함수 실행 이후, 그 다음 명령어부터 자식 프로세스에서 실행한다. 자식 프로세스가 부모 프로세스로부터 복사해올 때 PC값까지 복사해오기 때문에, 그다음번 명령어를 실행할 순서까지 복사가 된 것이다. 따라서 main 함수의 시작부분부터 되돌아가서 수행되는 것이 아니라, fork() 수행 이후 다음 명령어부터 실행된다. 

 

fork() 의 return 값

fork()명령어를 수행하게 된다면 부모 프로세스로 부터 복제해오기 때문에, 동일한 process여서 구분이 안될것이다. 이를 해결하기 위해서 fork() 함수는 pid 값을 return 하며, 부모 프로세스는 pid 값이 양수이다. 그리고 자식 프로세스는 pid 가 0 이다. 

 

exec() 시스템 콜 

exec() 는 완전히 새로운 프로세스를 실행하는 시스템 콜이다. 

int main()
{
	int pid;
    pid = fork(); # child process 생성 
    if (pid == 0)
    {
    	printf("Hello I am child \n");
     	execlp("/bin/date", "/bin/date", (char*)0); # child process가 /bin/date로 덮어쓰임
    }
    else if (pid > 0)
    	printf("Hello I am parent! \n");
}

위의 코드는 fork()로 새로운 child process를 생성하는데, printf 를 실행한 후 /bin/date라는 프로그램으로 완전히 덮어쓰게 된다. 즉 자식 프로세스는 /bin/date를 처음부터 실행하게 된다. 

int main(){
	printf("Hello I am child ! \n");
    execlp("/bin/date", "/bin/date", (char*)0); // 현재 프로세스가 /bin/date로 덮어쓰이게됨
    printf("Hello I am parent! \n"); // 실행되지 않음 
}

위의 예시는 fork()가 없다. 이 경우 실행중인 프로세스 자기자신이 execlp()에 의해서 /bin/date 프로그램으로 완전히 덮어쓰여지게 된다. 따라서 execlp 이후에 나오는 Hello I am parent는 실행되지 않는다. 

int main() {
	printf("1"); // 출력됨 
    execlp("echo", "echo", "3", (char *)0); // echo 로 덮여쓰여지므로 argument 3이 출력됨
    printf("2"); // 출력 안됨
}

// 출력 결과 
1 
3

위의 경우 1 이 출력된 이후에 echo 라는 프로그램 명령어로 덮여쓰여지므로 화면에 3 이 출력되며 2 는 출력되지 않는다. 

wait() 시스템 콜 

프로세스 A가 wait() 를 호출하면 

  • 커널은 child가 종료될 때까지 프로세스 A를 sleep 시킨다. (block 상태)
  • child process가 종료되면 커널은 프로세스 A를 깨운다. (ready 상태 )

자식 프로세스를 만든 다음에 wait() 를 하면 자식 프로세스가 종료되기까지를 기다리면서 현재 프로세스는 blocked 상태가 된다. 그후 자식 프로세스가 종료되면  커널이 현재 프로세스를 깨운다. 

main {
	int childPID;
    S1;
    
    if (childPID == 0)
    	child process code 실행 
    else { 
        // 부모 process는 block 상태 진입 
    	wait();
    }
    // child process의 실행 완료 후 실행되는 부분
    S2;
}

자원의 공유에 대해서 자식이 종료될 때까지 부모가 기다리는 (wait) 모델에 해당한다. 

exit() 시스템 콜 

자발적 종료 

마지막 statement 수행 후 exit() 시스템 콜을 통해 프로그램에 명시적으로 적어주지 않아도 main 함수가 리턴되는 위치에 컴파일러가 넣어준다.

비자발적 종료 

  • 부모 프로세스가 자식 프로세스를 강제 종료 시킨다.
    - 자식 프로세스가 한계치를 넘어서는 자원을 요청
    - 자식에게 할당된 태스크가 더이상 필요하지 않을 때 
  • 키보드로 kill, break 입력한 경우 
  • 부모 프로세스가 종료된 경우 
728x90