이화여자대학교 반효경 교수님의 2014년 Operating System 강의를 시청한 후 정리한 내용이다.
http://kocw.net/home/cview.do?cid=3646706b4347ef09

Process Creation

프로세스는 부모 프로세스로부터 생성되어 부모-자식 관계가 형성되어 트리 형태의 계층을 이룬다(모든 프로세스의 조상은 init이다). 프로세스의 생성 시 커널의 도움을 받는다. 생성된 자식 프로세스는 OS의 자원을 받아서 실행되는데, 이때 부모와의 자원 공유 여부에 따라 3가지로 나뉜다.

  • 부모 프로세스의 자원을 공유하지 않는 프로세스: 일반적으로 생성된 자식 프로세스는 부모와 별개의 존재이므로 서로 자원을 얻기 위해 경쟁한다.
  • 부모 프로세스의 일부 자원을 공유하는 프로세스
  • 부모 프로세스의 모든 자원을 공유하는 프로세스

시스템 콜 fork()를 사용하여 자식 프로세스를 생성하면, 자식의 메모리 공간에 부모의 binary나 data들을 그대로 복사한다. 그러나 자식 프로세스가 부모와 전혀 다르게 실행되길 바란다면 exec() 시스템 콜을 통해 자식의 메모리 공간에 새로운 프로그램의 binary를 올릴 수 있다.

Process Termination

(자식)프로세스는 exit() 시스템 콜을 이용하여, 종료 상태를 부모에게 넘기고 메모리와 버퍼 등의 자원을 반납하지만, 종료 상태와 PID는 커널에 아직 존재한다(task_struct). 이때 부모는 wait() 시스템 콜을 호출하여 종료 상태를 받고 자식이 종료된다. 이와 같이 프로세스가 자발적으로 종료할 수도 있지만, 모든 일을 끝내지 못하고 비자발적으로 종료하는 경우가 존재하는데, 부모가 자식을 종료하는 상황은 아래와 같은 것들이 있다.

  • 자식이 할당된 자원 사용량을 초과했을 때
  • 자식이 부모의 task에 더 이상의 도움이 필요 없을 때
  • 부모가 먼저 종료되었을 때

위 3번째의 경우는 고아 프로세스(Orphan Process)에 관한 내용이다. 고아 프로세스는 자식 프로세스보다 부모 프로세스가 먼저 exit()하여 부모를 잃는 프로세스를 말하는데, 이때 init이 해당 자식을 입양한 후 init 내부에서 주기적으로 호출되는 wait()을 통해 자식이 종료된다. 전체적으로 부모가 종료되기 전에 그 아래의 자식도 종료되는 흐름인데, 이를 cascading termination이라 한다.

이 외에도 Interrupt(kill, break)로 인해 비자발적으로 종료될 수 있는데, 이때 abort() 시스템 콜을 호출하여 프로세스가 비정상적으로 종료된다. 항상 부모 프로세스가 종료하기 전에, 자식 프로세스가 먼저 종료한다.
Abraham Silberschatz, Operating System Concepts 10th ed.

Copy On Write: 먼저 자식 프로세스를 생성할 때에는 바로 부모의 복사본을 만들지 않고 서로 공유하다가, 자식과 부모가 서로 다른 코드를 실행하여 서로 다른 스택을 생성하거나 데이터가 변동되는 시점에 부모의 복사본을 자식에 copy한다.


fork() system call

fork()는 프로세스의 메모리를 복제하여 binary가 동일한 자식 프로세스를 생성하는 시스템 콜이다. 함수의 반환 값은 부모 관점에서 자식의 PID를, 자식 관점에서 0을 반환한다. 복사 생성된 자식은 부모의 context를 물려받아 PC가 fork()함수 호출 이후를 가리키므로 그 시점부터 실행하게 된다.

exec() system call

exec() 시스템 콜을 호출하면 해당 프로세스에는 인자로 지정한 새로운 바이너리가 메모리에 덮어쓰이며, 새로운 프로세스로 실행한다. 만약 임의의 바이너리를 실행하는 프로세스를 생성하고 싶다면, fork()를 호출하여 새로운 프로세스를 생성하고, exec()을 이용하여 원하는 바이너리를 실행하도록 구현할 수 있다.

wait() system call

자식이 완전히 종료하기 위해서는 부모 프로세스는 자식의 종료 상태를 받아야 한다. wait() 시스템 콜은 자식의 종료 상태를 받을 때까지 block하는 함수이고, 자식이 종료하면 해당 함수는 종료된 프로세스의 PID를 반환한다. init은 고아 프로세스를 거두어 종료시키기 위해 주기적으로 wait() 시스템 콜을 호출하고 있다.

exit() system call

프로세스를 종료할 때는 exit() 시스템 콜을 사용하는데, 프로그래머가 명시를 하지 않아도 컴파일러가 main() 함수의 끝에 해당 시스템 콜을 추가한다. 프로세는 이 함수의 인자를 이용하여 부모에게 종료 상태를 전달할 수 있다.

Inter Process Communication (IPC)

기본적으로 프로세스는 자원을 얻기 위해 서로 경쟁하지만, 필요한 경우에 자원을 공유할 수 있다. 이때 사용하는 프로세스 간 협력 메커니즘 중 대표적으로 IPC가 있다.
Abraham Silberschatz, Operating System Concepts 10th ed.

  • Message Passing: 프로세스가 메세지를 주고받는 방법이다. 동기식과 비동기식 방법이 존재하는데, 동기식은 send, receive 명령을 통해 직접 데이터를 주고받고(Direct Communication), 비동기식은 커널이 전역으로 관리하는 메세지 큐에 데이터를 넣고 꺼내는 식으로 통신한다(Indirect Communication). 그러나 데이터를 큐-사용자 공간에서 복사하기 때문에 속도가 느리다.
  • Shared Memory: 두 프로세스가 같은 물리 메모리 영역을 공유하는 방법이다. Message Passing에 비해 데이터 접근 속도가 빠르지만, 공유 데이터가 유효하기 위해서는 동기화(Synchronization)가 매우 중요하다.
  • Thread: 스레드는 스택을 제외한 프로세스의 메모리 영역을 공유하므로 스레드 간 협력이 가능하다.

0개의 댓글