시스템 프로그래밍/Operating Systems: Three Easy Pieces

5. Interlude: Process API

맛있는김치찜 2020. 10. 11. 01:02

개요

Unix계열 운영체제에서는 fork(), exec() 계열의 API를 통해서 새 프로세스를 생성하고 wait() API를 통해서 다른 프로세스가 생성될 때까지 대기할 수 있게 한다.

 

 

fork() System Call

fork() 시스템콜은 새로운 프로세스를 생성하는데 사용한다.

이때 생성되는 프로세스는 fork()를 호출한 프로세스와 완전히 동일한 프로세스(심지어 pc까지도)이다!

이때 새로 생성된 프로세스는 0을 반환하여 부모 프로세스(fork()를 호출한 프로세스)인지 자식 프로세스(새로 생성된 프로세스)인지 구별할 수 있다.

위 코드의 실행 결과는 다음과 같은데 사실 부모, 자식 중 누가 먼저 실행되는지는 실행할 때마다 다르다.

누구를 먼저 실행시킬지 결정하는 운영체제의 스케쥴링 정책이 때에 따라 달라지기 때문이다.

 

 

wait() System Call

wait() 시스템콜과 함께 사용하면 부모 프로세스는 자식 프로세스의 수행이 끝날때 까지 대기하게 된다.

위의 경우(fork()만 사용)과는 달리 자식 프로세스가 먼저 실행된다는 것을 예상할 수 있다.

 

 

exec() System Call

exec() 시스템콜과 함께 사용하면 fork()를 호출하는 프로세스와는 다른 프로그램을 실행시킬 수 있다.

위 코드를 보면 부모 프로세스(else 부분)는 wait()를 통해 자식 프로세스가 끝나기를 기다리고 있다.

자식 프로세스(rc == 0)에서 exec()을 호출하게 되는데, 이때 실행할 프로그램의 이름과 그 프로그램의 매개변수를 함께 넘겨주면 자식 프로세스의 메모리 내용을 지우고 이전에 배운 생성 과정대로 완전히 새로운 프로세스가 생성된다.

실행 결과를 보면 20번째 줄의 "this shouldn't print out"이 출력되지 않는 것을 알 수 있는데 이는 printf 함수를 만나기 전에 새로운 프로세스(wc)로 바뀌었기 때문이다.

execvp(), execl()등 exec()계열의 API는 다양하다.

shell상에 man exec을 입력하면 자세한 내용을 검색해 볼 수 있다. 

 

Shell에서의 사용

Unix shell에서 위 API들은 꽤 중요하게 사용되는데 prompt에 명령어(ls -al, 현재 폴더안에 있는 파일들 나열. ls는 이러한 기능을 수행하는 프로그램의 이름)를 입력한다고 가정해보자. 

1. ls -al을 입력한다.

2. shell은 ls 프로그램이 어디에 위치해있는지를 찾는다(/bin에 위치).

3. 이 프로그램을 실행하기 위해 fork()를 통해 새로운 프로세스를 생성한다.

4. exec()의 매개변수로 함수이름(ls)와 그 매개변수(-al)를 넘겨주고 프로그램을 실행한다.

5. wait()을 통해 이 프로그램이 끝날 때까지 대기한다.

6. ls 함수가 끝나면 prompt가 다시 뜨고 사용자는 다시 명령어를 입력할 수 있다.