일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 개발
- 북리뷰
- OS
- vector
- 그래프
- Computer science
- 정석학술정보관
- 너비우선탐색
- cs
- 스택
- DP
- 브루트포스
- 컴공과
- Stack
- 오에스
- 컴퓨터공학과
- 오퍼레이팅시스템
- 정석
- 컴공
- coding
- 자료구조
- Operating System
- bfs
- 백준
- 알고리즘
- 코딩
- 구현
- 코테
- 문제풀이
- c++
- Today
- Total
Little Jay
[CS] Exceptional Control Flow : Process Termination - Computer System 3rd Edition by Bryant 본문
[CS] Exceptional Control Flow : Process Termination - Computer System 3rd Edition by Bryant
Jay, Lee 2022. 6. 29. 17:29Termination
Process는 세 가지 이유로 종료가 된다. 먼저 main 함수의 routine에 의해 자발적으로 종료가 되는 경우, exit함수로 자발적인 종료를 호출하는 경우, 마지막으로 종료를 수행하는 signal을 받을때이다.
다들 알고있겠지만 exit함수에 대한 간단한 소개를 하고 넘어가자면, exit함수는 말그대로 process를 terminate시킨다. 이 함수에는 번호가 들어가는데, 그 범위는 0~255까지 들어갈 수 있으며 0은 정상종료의 의미, 0이 아닌 경우에는 error상황이다. C의 stdlib.h 헤더파일에는 void atexit(void *(func) (void)); 가 들어가있다. 자세한 설명은 아래 링크의 블로그를 참조하면 되겠다. 이 함수는 exit할 때 다른 함수들을 호출하는데 사용한다. _exit(0); 을 많이 사용하는데 이렇게 되면 exit handler를 불러 atexit가 매개변수로 받는 함수포인터를 찾아서 실행시키고 종료하게 된다. 특이한 점은 이 atexit 함수에 등록된 순서의 반대로 실행한다는 것이다.
Zombie Process
Linux에서 Process를 종료하는 경우, 특히 exit 함수를 써서 Process를 종료시킬 때 Process의 memory, code, stack 등의 state는 삭제되지만 PCB는 남아있다. PCB는 운영체제가 프로세스를 제어하기 위해 정보를 저장해 놓는 곳으로, 프로세스의 상태 정보를 저장하는 구조체이다. 프로세스 상태 관리와Context Switching)을 위해 필요하며, PCB는 프로세스 생성 시 만들어지며 주기억장치에 유지된다. PCB는 남아있지만 process를 더 이상 실행시키지는 못한다. 이 PCB는 System에서 바로 지워지지 않고 일정시간 남아있게 된다. 즉, exit를 하더라도 완전히 지워지는 것이 아니고 process를 실행할 수 없는 애매모호한 상태로 남아있는 것이다. PCB까지 없어지는 시점은 Parent Process가 "reaped" 할때까지 기다린다. 해석하면 수확하다라고 하는데 그냥 reaped라고 계속 부르겠다. 어째뜬 Parent Process가 reap할때 까지 기다려야하기 때문에 PCB는 운영체제에 둥둥 떠다니고 기능하고 있지 않기 때문에 이를 Zombie Process라고 명명한다. Reaping하는 것은 Parent Process에게 exit status를 제공하는 것이다. Parent Process가 Child Process의 exit번호를 받고 정상적으로 종료가 되었는지 확인한 후에 Kernel이 Zombie 상태인 Process를 삭제한다. Reaping은 wait 함수를 통해 확인할 수 있다.
Zombie Process가 한 개일 경우에는 사실 큰 영향이 없다. 그러나 Zombie Process의 수가 많아지고, Parent Process가 Reap하지 않고 terminate된다면 orphan으로 남아있을 것이고, PCB도 운영체제의 자료구조이기 때문에 data 정보를 가지고 있다. 따라서 이는 명백한 System Resource에 대한 자원소모이고, System에서 사라지지 않고 축적이 되며 사라지지 않을 것이다. 따라서 Zombie Process를 줄이고 관리하는 Modeling이 필요하다.
Orphan Process
잠깐 위에서 언급했는데, Orphan Process라는 용어가 있다. Child Process가 Parent의 wait을 기다리다가 Parent가 그냥 종료되어 버리면 Child Process는 Parent를 잃게된다. getppid() 함수를 통해 Parent Process를 pid번호를 확인할 수 있는데, 만약 Parent Process가 terminate된다면 Child Process의 parent는 Linux의 최상단인 Init Process가 Parent Process가 된다. 아래의 코드를 직접 실행시키면 Child Process의 ppid가 어느 순간 바뀌는 것을 볼 수 있다.
//코드 출처: https://codetravel.tistory.com/31
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t childPid;
int i;
childPid = fork();
if(childPid > 0) { // 부모 프로세스
printf("부모 PID : %ld, pid : %d\n",(long)getpid(), childPid);
sleep(2);
printf("부모 종료\n");
exit(0);
}
else if(childPid == 0){ // 자식 코드
printf("자식 시작\n");
for(i=0;i<5;i++) {
printf("자식 PID : %ld 부모 PID : %ld\n",(long)getpid(), (long)getppid());
sleep(1);
}
printf("자식 종료\n");
exit(0);
}
else { // fork 실패
perror("fork Fail! \n");
return -1;
}
return 0;
}
Reference
Randal E. Bryant, & David R. O’Hallaron. (2016). Computer Systems A Programmer’s Perspective Third edition. Carnegie Mellon University: Pearson.