Process

오늘날 우리는 컴퓨터로 여러가지 일을 동시에 합니다. 지금도 웹브라우저로 필요한 정보를 찾는 동시에 화면을 반으로 나누어 한쪽에 초고를 띄워놓고 나머지 반쪽 화면을 통해 이 글을 적고 있습니다. 어떻게 이런 일이 가능한 걸까요? 그 비밀은 프로세스Process 라는 개념에 있습니다. 이번 글에서는 프로세스의 내부보다는 프로세스 그 자체에 대한 내용을 중점적으로 살펴봅니다.


프로세스의 탄생

컴퓨터라는 물건이 탄생한지 얼마 되지 않은 초창기 시절, 컴퓨터는 지금과 달리 한 번에 하나의 프로그램만 실행할 수 있는 스페셜리스트였다. 운영체제라는 개념이 존재하지 않았고, 여러 사람이 같이 써야 할 만큼 비쌌다. 그 시절 프로그램은 주로 천공 카드punched card 였고, 컴퓨터는 주변기기를 통해 프로그램에 기록된 명령을 순서대로 읽고 그에 맞는 명령을 실행했다. 컴퓨터를 사용하고자 하는 사람은 자신의 프로그램과 데이터를 걸어놓고 먼저 신청한 사람의 작업이 끝날 때까지 기다려야 했다. 이때 한 자리를 차지한 프로그램과 데이터을 합쳐 작업job 이라 불렀고, 이를 컴퓨터가 실행할 때 작업의 최소 단위를 태스크task 라 불렀다.[1][2][3]

컴퓨터가 발전하면서 이제는 저장 장치에 프로그램을 기억해 두었다가 실행될 때 메모리 위에 올려 실행하게 되는데, 상술한 개념들이 이때 오늘날 사용되는 프로그램과 프로세스의 개념으로 변화하게 된다. 프로그램은 이제 파일 단위로 저장된 명령어들의 집합이며, 프로세스는 실행 중인 프로그램의 상태, 컴퓨터에서 연속적으로 실행되고 있는 프로그램의 '동적인 상태'다.

프로그램에서 프로세스로

그렇다면 프로그램은 어떻게 프로세스가 됐을까? 프로세스가 프로그램으로부터 생성되는 과정을 자세히 들여다보자.

프로세스 생성하기

우선 프로세스가 실행되기 위해서는 하드웨어에 접근할 수 있어야 한다. 그런데 이 하드웨어는 운영체제가 통제권을 쥐고 있어서 하드웨어에 접근하기 위해서는 운영체제의 허락이 있어야 한다. 그렇기 때문에 프로세스는 커널, 특히 모놀리식 커널Monolithic Kernel [4]에서 생성된다. 사용자의 프로세스가 새 프로세스나 새 스레드를 생성하면, 시스템 호출 인터페이스가 요청을 받아서 커널로 전달하고, 커널에서는 이 요청에 대해 새 작업을 생성한다. 이 작업은 스케쥴러Scheduler 라는 모듈의 대기열에 배치되며 때가 되면 CPU 등 컴퓨터의 자원을 사용할 수 있게 된다.

커널이 새 프로세스나 스레드를 스폰하라는 요청을 받았을 때, 커널에서는 특정 실행 파일에 대한 핸들러Handler 를 종류에 따라 찾고, 핸들러에 맞는 실행 파일을 주 기억 장치(보통 RAM)로 불러올 로더 프로그램Loader Program 을 사용한다. 그리고 프로세스를 실행하기 위해 로더 프로그램은 다음과 같은 작업을 수행한다.

운영체제는 이렇게 만들어진 프로세스에 각각의 번호(Process Identification Number, PID)를 붙여 관리한다. 프로세스를 만들 때는 현재 실행 중인 프로세스에서 만들게 되는데, 이때 현재 실행 중인 프로세스를 부모 프로세스Parent Process, 새로 생성되는 프로세스를 자식 프로세스Child Process 라고 부른다. 부모 프로세스로부터 자식 프로세스가 생겨나기 때문에 프로세스의 의존을 나타내는 그래프는 트리의 형태를 띤다.

또한 새로운 프로세스를 만들 때는 세 가지 옵션을 설정할 수 있다.

실제로 프로세스를 생성하는 과정은 분량 상의 문제로 여기서 다루지 않고 다른 글에서 자세히 다루게 될 것이다.

프로세스의 구조

이렇게 만들어진 프로세스는 프로그램의 동적 인스턴스이며, 그 상태가 시시각각 변화하는 역동적인 과정이다. 그렇지만 당연히 고정된 골격이 있고, 이제 그 골격을 알아볼 차례다.

내부 구조

운영체제의 관점에서, 일반적인 프로세스의 내부 구조는 다음과 같다.[6]

메모리 내부에 존재하는 프로세스의 레이아웃 예시

프로세스에는 크게 네 개의 구역이 존재하는데, 각각 다음과 같다:

프로세스 내부를 직접 만져보고 자세하게 파헤치는 과정은 분량 문제로 여기서 다루지 않고 다른 글에서 자세히 다루게 될 것이다.

Process Control Block

운영체제는 프로세스를 주기적으로 바꿔주면서 CPU가 최대한 쉬지 않고 일하게 만들어야 하기 때문에, 프로세스의 내부 구조와는 별개로 프로세스를 하나의 물체로 다룰 필요가 있다.

PCB의 레이아웃

그래서 운영체제는 프로세스를 하나의 물체처럼 추상적으로 취급하는데, 이때 하나의 프로세스를 Process Control Block(이하 PCB)이라는 하나의 객체로 취급된다.
PCB는 프로세스마다 가지고 있는, 프로세스를 통제하기 위한 모든 정보들의 집합으로, Task Control Block라 부르기도 한다. 여기에는 다음의 정보가 포함되어 있다.

PCB에 대한 자세한 내용은 분량 상의 문제로 다른 글에서 자세히 다루게 될 것이다.

메모리 위의 프로세스

가상 메모리와 물리 메모리

앞서 프로세스의 레이아웃을 살펴보았다. 그러나 실제로 프로세스가 메인 메모리에 저장되어 있는 모습을 이해하기 위해서는 소프트웨어의 관점에서 레이아웃을 볼 때와는 다른 관점으로 접근할 필요가 있다. 실제 프로세스는 메인 메모리 내 여기저기에 흩어져 있으며, 운영체제는 메모리 가상화Memory Virtualization 를 통해 실제로는 흩어져 있는 프로세스를 하나의 통합된 주소 공간으로 파악한다.

하드웨어의 관점에서 보는 프로세스는 분량 상의 문제로 다른 글에서 자세히 다루게 될 것이다.

프로세스 활용하기

현실에서는 프로세스를 수십 개 다루는 것 정도 쯤이야 기본이다. 그래서 그 수십 개의 프로세스를 조화롭게 사용하기 위한 여러가지 기술이 있다. 그 중 대표적인 것이 바로 스케줄러프로세스 간 소통(Inter-Process Communication, IPC)인데, 분량 상 여기서 다루지는 않을 것이다.

프로세스 종료하기

프로세스가 모든 일을 마치고 종료될 때, 부모 프로세스는 상태 값을 받을 수 있다. 또한 자식 프로세스에게 할당됐던 자원들이 운영체제에 의해 해제된다. 시스템 호출System Call 이나 코드에 의해 자식 프로세스가 강제로 종료될 수 있는데, 이때 운영체제에 따라 부모 프로세스가 종료되면 자식 프로세스가 모두 멈추거나Cascading Termination , 모든 프로세스의 부모인 최초의 프로세스를 부모로 다시 정하기도 한다.

이 과정에서 실제 프로세스는 종료했지만 부모 프로세스가 그 상태를 확인하지 못했을 때(ex. POSIX API를 사용하는 환경에서 wait() 함수를 호출하기 전에 자식 프로세스가 먼저 종료됨) 이 프로세스를 좀비 프로세스Zombie Process라고 부른다. 실제로는 종료된 프로세스지만, 이들을 관찰하는 부모 프로세스의 입장에서는 아직 종료된 프로세스가 아니다.

반대로 부모 프로세스가 종료를 위해 시스템 호출을 사용하지 못하고 먼저 종료된 경우, 자식 프로세스는 고아 프로세스Orphan Process가 되어 홀로 남겨진다. 종료 후 상태에 대한 정보를 넘길 부모 프로세스가 없는 상황을 해결하기 위해 POSIX 환경에서는 init 프로세스를 이들의 새로운 부모 프로세스로 지정한다.

실제로 프로세스를 종료시키는 과정은 분량 상의 문제로 여기서 다루지 않고 다른 글에서 자세히 다루게 될 것이다.


참고 자료 & 더보기

참고 자료

더보기


  1. 케임브리지 대학 수학 연구소의 컴퓨터 EDSAC에 대한 1951년 영상을 통해 초창기 컴퓨터가 어떻게 사용되었는지 엿볼 수 있다. ↩︎

  2. 자세한 내용은 이 링크를 통해 확인할 수 있다. 오늘날 Job과 Task는 구분없이 사용되기도 하며 그 정의가 모호하다. ↩︎

  3. Kamran, A. (2022)에 의하면, 커널 수준에서 프로세스나 스레드를 다룰 때 작업job 이라는 용어를 프로세스나 스레드 대신 사용하기도 한다. ↩︎

  4. 하나의 주소 공간을 갖는 커널 프로세스 한 개로 구성되는 커널이며, 이 커널 프로세스는 커널이 제공하는 모든 서비스를 포함한다. ↩︎

  5. 멀티스레드 프로그램에서 가장 중요한 스레드다. 실행 흐름의 측면에서 가장 처음 실행되고 가장 마지막으로 종료되는 스레드이며, 프로세스의 다른 모든 스레드가 시작되는 기원이다. ↩︎

  6. 이 레이아웃은 운영체제가 프로세스를 인식하는 형태이며, 이 형태를 가상 주소 공간Virtual Address Space 이라 부르기도 한다. ↩︎