1. Process 생성과 소멸(fork)
:기본적으로 부모프로세스가 자식 프로세스를 생성하는 방식으로 프로세스를 생성할 수 있다.
- A tree of processes
- 이때 자식, 부모 프로세스 실행측면에서 두가지 방식이 있다.
- 부모 프로세스가 자식 프로세스와 concurrent하게 실행되는 경우
- 부모 프로세스가 wait하면서 자식프로세스의 종료를 기다리는 경우
- 프로세스의 명령어 메모리 주소 공간에 두가지 방식이 있다.
- 부모 프로세스의 명령어 주소공간을 복제한다.-자식 프로세스가 부모 프로세스와 동일한 경우.
- 새로운 프로그램을 메모리에 로딩한다.
뒤에 예제를 통해 자식 프로세스가 어떻게 실행되는지 알아보자.
**결론적으로 자식 프로세스는 concurrent하게 실행되면서 부모 프로세스의 명령어 주소 공간을 복제한다.
- fork
:fork()함수는 부모프로세스 안에서 새로운 자식 프로세스를 만드는 함수이며 특징적으로 부모 프로세스는 wait 하지않고 concurrent하게 자식 프로세스와 같이 작동된다.
또한, 자식 프로세스는 부모프로세스와 같은 pc, registers, open files내의 정보를 사용한다. 즉,부모 프로세스의 pcb의 정보를 일부 복제하여 새로운 pcb를 만들게 된다. pc등의 값 또한 복제해 오기때문에 자식 프로세스와 부모프로세스 모두 fork다음 문장부터 실행하게 된다.
memory 영역의 경우 도 새로운 메모리공간을 할당받은후 부모프로세스의 메로리 공간의 내용을 똑같이 복사해 온다.
return 값은 pid이고 negative 인 경우 자식 프로세스 형성이 실패한 경우, zero인 경우 자식 프로세스 내에서 pid를 return하는 경우, positive인 경우 부모 프로세스 내에서 fork()한 프로세스의 pid 를 리턴하는 경우이다.
- exec
: 호출된 프로세스를 다른 프로세스로 덮 어버리는 것으로 exec fork 하여 새로운 복제된 자식 프로세스를 만든후 exec로 다른 프로세스로 만들어준다.
fork에 대한 올바른 이해.
- fork시 전역변수는?
위 코드를 실행시 20이 먼저 출력되고 그다음에 5가 출력된다.
그 이유는 fork이후 textsegment를 제외한 나머지 data segment등의 메모리 공간은 새로 할당 받게 되므로 int value 라는 전역변수는 부모프로세스와 자식프로세스에서 서로 다르게 정의된다. pid가 0일때는 자식 프로세스에서 20이 출력 되고, 자식 프로세스 termination이후에는 부모 프로세스가 실행되어 5가 출력된다.
- fork시 자식, 부모프로세스에서 명령어 실행위치는?
:항상 fork()한 부분 다음부터 실행된다.
프로세스가 총 몇개 생성될까?
fork()를 하나했을때 프로세스가 2개
fork()를 위에 하나더 추가했을때 프로세스2개인 프로세스가 자식,부모로 각각 두개씩 생기므로 4개
그 다음 8개 이렇게 2^n으로 늘어난다.
2. exec()-loader()
:Excutable file의 binary code를 현재 프로세스의 code segment로 복사해 와 fork()후에 다른 프로세스로 만들어준다.
3. 자식 프로세스 형성 이후 필요한 wait()
: wait 함수는 자식 프로세스가 종료되기 전까지 대기하다가 자식 프로세스가 종료될 경우 신호를 받고 이때, 다시 부모 프로세스를 실행하는 함수이다. return 값으로 자식 프로세스의 pid를 주고 매개변수 int 포인터로 자식 프로세스의 exit status를 얻을 수 있다. wait 함수를 실행해야 자식 프로세스 종료시 남는 약간의 메모리를 회수할 수 있으므로 자식 프로세스를 위해 wait 함수를 적절히 사용하여야 한다.
- fork와 wait
fork로 자식 프로세스를 생성하면 자식 프로세스는 ready Q에 들어가기 때문에 부모프로세스가 먼저 실행된다. 이 때 wait()을 사용하면 부모프로세스를 wait Q에 넣고 자식 프로세스를 먼저 실행시킨후 자식 프로세스가 종료되면 부모프로세스가 실행된다.
. 자식 프로세스 형성 이후 올바르게 wait되지 않는 경우.
1) orphan process
:부모 프로세스가 wait()호출하지 않아 자식 프로세스가 끝나기 전에 부모프로세스가 종료되는 경우
고아 프로세스의 문제점은 부모 프로세스가 사라졌으므로 wait를 통해 자신의 종료 상태를 회수해줄 프로세스가 사라졌다는 것이다. 이 경우 좀비 프로세스가 될 수 있는데 이를 방지하기 위해 init 프로세스가 부모프로세스가 되어 wait 함수를 호출함으로서 고아 프로세스의 종료상태를 회수해줌.
2) zombie process
:프로세스가 종료되었음에도 불구하고 메모리상에서 프로세스에 대한 정보가 사라지지 않은 상태.
자식 프로세스는 끝났지만 아직 부모 프로세스가 wait를 실행하지 않은 경우. ex)daemon process, background process
자식 프로세스가 종료되더라도 일부의 정보는 메모리에 남아있게 되는데 wait를 실행하면 부모프로세스에게 자식 프로세스가 완전히 종료되었음을 알릴 수 있고 이 경우 남아있던 잔여 메모리가 제거된다.wait을 실행하지 않으면 자식 프로세스의 정보가 메모리상에 일부 남은것이 회수되지 못하고 쌓이게 된다.
결론적으로, 자식 프로세스가 fork()로 호출되었다면 부모 프로세스에서 지속적인 부모프로세스 진행을 원하는 경우라 하더라도 자식 프로세스가 termination하는 것을 처리해주기 위하여 이후에 wait를 호출하여 자식 프로세스의 termination을 감지해 주어야 한다는 것이다.