시스템 콜의 종류 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 입력한 경우
- 부모 프로세스가 종료된 경우
'Computer Science > 운영체제' 카테고리의 다른 글
[운영체제] 10. CPU Scheduling (0) | 2023.06.25 |
---|---|
[운영체제] 9 (2) Process Management (0) | 2023.06.25 |
[운영체제] 8.Process Management 1 - 프로세스의 생성과 종료 (0) | 2023.06.25 |
[운영체제] 7. Process 3 - Thread의 장점 2 (0) | 2023.06.18 |
[운영체제] 6. Process (2) - Thread와 Thread의 장점 (0) | 2023.06.18 |