프로세스

디스크에 있는 것은 프로그램, 메모리에 로드된 것은 프로세스라고 한다. 프로세스는 Stack, Heap, Data, Code로 나뉜다.

+---------------+ max
|     stack     |
+-------+-------+
|       |       |
|       v       |
|               |
|       ^       |
|       |       |
+-------+-------+
|     heap      |
+---------------+
|     data      |
+---------------+
|     text      |
+---------------+ 0

Process State

프로세스의 상태는 현재 활동에 따라 달라진다.

                         +------------interrupt------------+
                         v                                 |
+-----+              +-------+                        +----+----+          +------------+
| new +---admitted-->| ready +---scheduler dispatch-->| running +---exit-->| terminated |
+-----+              +-------+                        +----+----+          +------------+
                         ^           +---------+           |
                         +-----------+ waiting |<----------+
         I/O or event completion     +---------+     I/O or event wait
  • New: 프로세스가 처음 생성되었을 때.

  • Ready: 프로세스가 프로세서에 할당되기를 기다릴 때.

  • Running: 프로세스가 할당되어 실행될 때.

  • Waiting: 프로세스가 이벤트를 기다릴 때.

  • Terminated: 프로세스가 실행을 마쳤을 때.

Process Control Block (PCB)

각각의 프로세스는 자신의 정보 묶음인 PCB를 가지고 있다. PCB에는 프로세스 상태와 프로그램 카운터, 메모리 한계, 레지스터 정보 등이 담겨있다.

  • Process state: 프로세스의 상태.

  • Program counter: 해당 프로세스가 이어서 실행해야 할 명령의 주소를 가리키는 카운터.

  • CPU registers: 프로세스가 인터럽트 이후 올바르게 작업을 이어가기 위해 참조하는 CPU 레지스터 값.

  • CPU-scheduling information: 프로세스의 중요도, 스케줄링 큐 포인터 등 스케줄링 파라미터 정보.

  • Memory-management information: base, limit 레지스터 값, 페이지 테이블 등 메모리 시스템 정보.

  • Accounting information: 사용된 CPU 총량, 프로세스 개수, 시간 제한 등.

  • I/O status information: 프로세스에 할당된 입출력 장치 목록, 열린 파일 목록 등.

Threads

프로세스를 쪼개 하나의 프로세스 안에서 동시에 여러 작업을 처리할 수 있다. 지금까지는 싱글 스레드 프로세스를 전제하고 살펴봤다. 싱글 스레드 프로세스는 한번에 하나의 작업만 할 수 있다. 가령 워드 프로세서 프로그램을 실행한다면, 글자를 타이핑할 때 같은 프로세스 안에서 동작하는 문법 교정기가 동시에 동작할 수 없다. 챕터 4에서 자세히 다룬다.

Process Scheduling

멀티프로그래밍의 목적은 CPU를 최대로 사용하기 위해 항상 일부 프로세스를 실행하는 것이다. 타임쉐어링의 목적은 프로세스 간에 CPU를 자주 전환함으로써 사용자가 각 프로그램이 실행되는 동안 서로 상호작용할 수 있도록 만드는 것이다. 이러한 목적을 달성하기 위해 프로세스 스케줄러는 CPU에서의 프로그램을 실행을 위해 사용 가능한 프로세스를 선택하며, 어떤 프로세스를 프로세서에 할당할 것인가 결정하는 일을 프로세스 스케줄링이라고 한다.

Scheduling Queues

프로세스가 시스템에 들어오면 잡 큐(Job queue)에 들어간다. 잡 큐는 시스템의 모든 프로세스로 구성되어있다. 메인 메모리에서 실행을 기다리는 ready 상태의 프로세스들은 레디 큐(Ready queue)에 쌓인다. 입출력 장치를 기다리는 프로세스들은 디바이스 큐(Device queue)로 들어간다.

Schedulers

레디 큐에 프로세스를 옮기는 것은 잡 스케줄러, 또는 Long-term 스케줄러라고 한다. 프로세스를 프로세서에 할당하는 것은 CPU 스케줄러, 또는 Short-term 스케줄러라고 한다. Long-term 스케줄러는 CPU 밖에서 가끔 수행된다. Short-term 스케줄러는 그 반대다.

Context Switch

프로세스가 실행되다가 인터럽트가 발생해 운영체제가 개입하여 프로세서에 할당된 프로세스를 바꾸는 것을 말한다. 시스템 콜을 사용해야 하는 경우 프로세스가 자체적으로 처리할 수 없기 때문에 운영체제가 개입해야 한다. 프로세서가 다른 프로세스로 스위치할 때, 시스템은 작업중이던 프로세스의 상태를 저장하고 새로운 프로세스의 상태를 로드한다. 컴퓨터과학에서 컨텍스트는 내 시스템에서 활용 가능한 모니터링된 정보들을 의미한다. 프로세서 입장에서 컨텍스트는 PCB이기 때문에 PCB 정보가 바뀌는 것을 컨텍스트 스위치라고 부른다. 컨텍스트 스위치는 오버헤드가 발생하는 작업이기 때문에 너무 자주 일어나면 성능을 저하한다.

Operations on Processes

대부분의 시스템에서 프로세스는 동시에 실행될 수 있고, 이들은 동적으로 생성되거나 삭제될 수 있다. 시스템은 프로세스 생성, 삭제 메커니즘을 제공해야 한다.

Process Creation

프로세스는 트리 구조로 되어 있다. 즉, 부모 프로세스가 자식 프로세스를 만든다. PCB에 저장된 pid값으로 프로세스를 식별하는데, 이는 운영체제가 정해준 고유 번호다. 프로세스 생성은 플라나리아 번식과 유사하다. 시스템 콜의 fork() 함수를 호출하면 부모 프로세스는 자신과 똑같은 자식 프로세스를 생성한다. 자식 프로세스는 exec()를 통해 내용을 모두 바꾼다. fork() 함수는 부모 프로세스에겐 자식 프로세스의 pid를, 자식프로세스에겐 0을 반환한다. 부모 프로세스와 자식 프로세스는 동시에 작동한다.

Process Termination

exit()를 호출하면 프로세스를 종료시킬 수 있다. 부모 프로세스가 자식 프로세스보다 먼저 종료되면 자식 프로세스는 그 상위 프로세스를 부모 프로세스로 바라본다. 자식 프로세스가 종료되었는데, 부모 프로세스가 자식 프로세스가 반환한 정보를 회수하지 않으면 자식 프로세스는 종료되었음에도 정보가 메모리에 남아 있는 좀비 프로세스가 된다.

Interprocess Communication (IPC)

프로세스는 독립적으로 동작하거나 서로 협력하며 동작할 수 있다. 협력하는 프로세스들은 통신하며 서로에게 영향을 미친다. IPC 모델에는 메시지 패싱(Message passing)과 공유 메모리(Shared memory)가 있다.

Message Passing

메시지 패싱은 우편이다. 송신 프로세스가 정보를 받는 수신 프로세스에게 커널을 통해 정보를 전달하며, 수신 프로세스도 커널에 접근해 정보를 수신한다. 메시지 패싱은 컨텍스트 스위치가 발생하기 때문에 속도가 느리다. 다만 커널이 기본적인 기능을 제공하므로 공유 메모리 방식에 비해선 구현이 쉽다.

Shared Memory

공유 메모리는 게시판이다. 특정 메모리 공간을 두 프로세스가 함께 사용하며 정보를 주고 받는다. 커널을 거치지 않기 때문에 속도가 빠르지만 메모리에 동시 접근하는 것을 방지하기 위해 프로그래머가 따로 구현을 해줘야 한다.

Producer-Consumer Problem

협력하는 프로세스 중 정보를 생산하는 프로세스를 생산자(Producer), 정보를 소비하는 프로세스를 소비자(Consumer)라고 부른다. 생산자-소비자 문제는 두 프로세스가 동시에 동작할 때 일어나는 이슈를 말한다. 보통 정보가 생산되는 속도가 소비하는 속도보다 빠르기 때문에 동기화 문제가 발생하는데, 이를 해결하기 위해 생산된 데이터를 담아두는 버퍼(Buffer)를 사용한다. 크기에 한계가 있는 버퍼를 유한 버퍼(Bounded buffer), 버퍼의 시작과 끝을 이어붙여 크기가 무한한 버퍼를 무한 버퍼(Unbounded buffer)라고 한다.

Synchronization

메시지 패싱의 동기화 문제를 해결하기 위해 blocking 방식과 non-blocking 방식이 사용된다.

  • Blocking send: 수신자가 메시지를 받을 때까지 송신자는 block된다.

  • Blocking receive: 메시지를 수신할 때까지 수신자는 block된다.

  • Non-blocking send: 송신자가 메시지를 보내고 작업을 계속한다.

  • None-blocking receive: 수신자가 유효한 메시지나 Null 메시지를 받는다.

Sockets

소켓은 서버와 클라이언트가 통신하는 방식이다. IP주소와 포트 정보가 있으면 클라이언트는 네트워크를 통해 서버 프로세스에 접근할 수 있다. RPC(Remote Procedure Calls)는 프로세스와 프로세스가 네트워크로 이어져 있을 때 발생하는 호출을 말한다. 서버와 클라이언트가 통신할 때는 IP주소와 포트를 래핑해서 Stub으로 만들어 전송한다.

Pipes

파이프는 부모 프로세스와 자식 프로세스가 통신할 때 사용하는 방식이다. 말 그대로 프로세스 사이에 파이프를 두고 정보를 주고 받는 건데, 파이프는 단방향 통신만 가능하기 때문에 양방향으로 정보를 주고 받으려면 두 개의 파이프가 필요하다. (파이프는 파일이다.) 파이프에 이름을 붙인 named pipe를 사용하면 꼭 부모-자식 관계가 아니더라도 파이프를 이용해 통신할 수 있다.

Last updated