Process의 생성과 제어를 위한 4가지 SystemCall에 대해 알아보자.
- Fork
- Wait
- Exec
- Exit
Fork
새로운 Process를 생성한다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // 주목
if (rc < 0) {
exit(1);
} // (1) fork 실패
else if (rc == 0) { // (2) child 인 경우 (fork 값이 0)
printf("child (pid : %d)", (int) getpid());
}
else { // (3) parent case
printf("parent of %d (pid : %d)", rc, (int)getpid());
}
}
pid: 29147
parent of 29147 (pid : 29146)
child (pid : 29147)
새롭게 생성되는 자식 프로세스는 새로운 PID를 갖게되어 호출한 부모 프로세스를 그대로 복사한다.
복사를 통해 자식 프로세스는 부모와 완전히 독립된 물리 메모리 공간을 갖는다.
(단, 파일 디스크립터는 동작이 다르다.)
- 자식 프로세스는 부모 파일 디스크립터의 복사본을 갖는다. 이 디스크립터는 같은 오브젝트를 참조하므로 후속 읽기 또는 쓰기 영향을 미칠 수 있다.
Wait
child 프로세스가 종료될 때까지 기다린다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // 주목
if (rc < 0) {
exit(1);
} // (1) fork 실패
else if (rc == 0) { // (2) child 인 경우 (fork 값이 0)
printf("child (pid : %d)", (int) getpid());
}
else { // (3) parent case
int wc = wait(NULL) // 추가된 부분
printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
}
pid: 29146
child (pid : 29147)
parent of 29147 (wc: 29147 / pid : 29146)
parent가 먼저 실행되더라도 wait()를 사용해서 child가 끝나기 전에는 return 하지 않으므로, 반드시 child가 먼저 종료된다.
자식 프로세스가 고아 프로세스가 되는 것을 방지한다.
Exec
단순 fork는 동일한 프로세스의 내용을 여러 번 동작할 때 사용한다.
child에서는 parent와 다른 동작을 하고 싶을 때는 exec을 사용할 수 있다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
printf("pid : %d", (int) getpid()); // pid : 29146
int rc = fork(); // 주목
if (rc < 0) {
exit(1);
} // (1) fork 실패
else if (rc == 0) { // (2) child 인 경우 (fork 값이 0)
printf("child (pid : %d)", (int) getpid());
char *myargs[3];
myargs[0] = strdup("wc"); // 내가 실행할 파일 이름
myargs[1] = strdup("p3.c"); // 실행할 파일에 넘겨줄 argument
myargs[2] = NULL; // end of array
execvp(myarges[0], myargs); // wc 파일 실행.
printf("this shouldn't print out") // 실행되지 않음.
}
else { // (3) parent case
int wc = wait(NULL) // 추가된 부분
printf("parent of %d (wc : %d / pid : %d)", wc, rc, (int)getpid());
}
}
Exit
exit 함수를 호출하면 어떤 종료 코드를 사용하던 정상 종료가 된다.
exit(1)
참고
'Operation > OS' 카테고리의 다른 글
OS - 세마포어(Semaphore)와 뮤텍스(Mutex) (+ Race Condition) (0) | 2022.10.03 |
---|---|
블로킹(Blocking)과 논 블로킹(Non-Blocking)! (0) | 2022.07.06 |
OS - 프로세스와 스레드 차이 (0) | 2022.07.05 |
OS - 교착 상태(Deadlock) 정리! (0) | 2022.04.19 |