프로세스

mydailylogs
|2022. 12. 6. 23:26

프로그램을 오늘날 시스템에서 실행할 때, 마치 시스템 전체에서 단 하나의 프로그램만 돌아가는 것 같은 착각이 들게 된다. 즉 우리의 프로그램은 시스템의 프로세서와 메모리를 독점하여 사용하는 것처럼 보인다. 이러한 착각은 프로세스라는 개념에 의해서 이뤄진다.

프로세스의 고전적 정의는 실행 프로그램의 인스턴스이다. 시스템 내의 각 프로그램은 어떤 프로세스의 컨텍스트에서 돌아간다. 이때 컨텍스트는 프로그램이 정확하게 돌아가기 위해 구성된 상태라고 생각할 수 있다. 예를 들어 메모리에 저장된 프로그램의 코드(.text)와 데이터(.bss, .data, stack, heap), 프로그램 카운터, 환경 변수 열려있는 파일 디스크립터 등이 그것이다. 

사용자가 실행 목적 파일의 이름을 쉘에 입력해서 프로그램을 돌릴 때마다 쉘은 새로운 프로세스를 생성하고 실행 목적 파일을 새롭게 생성된 프로세스의 문맥에서 실행한다. 

또한 응용 프로그램에서도 유저는 fork 를 통해서 새로운 프로세스를 만들 수 있으며, 이때 생성된 프로세스의 문맥 내에서 자신의 코드나 다른 응용 프로그램의 코드를 돌릴 수 있다.

프로세스는 독립된 논리적 제어 흐름이다.

프로세스는 다른 많은 프로그램들이 일반적으로 시스템에서 동시에 실행되고 있음에도 불구하고 각 프로그램이 프로세서를 독점적으로 사용하는 것처럼 착각하게 한다. 만약 우리가 디버거를 사용하여 프로그램의 실행을 한 단계씩 진행해보면, 프로그램 카운터(PC) 값을 관찰할 수 있을 것이다. 이러한 일련의 PC 값을 논리적 제어 흐름 또는 단순히 논리적 흐름이라고 부른다.

그림 1. 논리적 제어흐름

위의 그림을 살펴보자. 세 개의 프로세스가 실행되고 있으며 이 프로세서의 하나의 물리적 흐름은 각 프로세스에 대해서 한 개씩 세 개의 논리적 흐름으로 나뉘어진다. 예제에서 세 개의 논리흐름들이 서로 중첩되지 않는다는 점을 중점적으로 살펴보자.

프로세스 A는 잠시동안 돌다가 B가 실행되고 C가 실행된다. 다시 A가 동작하다가 다시 C가 실행된다. 해당 그림의 요점은 하나의 프로세서를 사용해서 여러 프로세스들이 교대로 돌아간다는 점이다. 각 프로세스는 자신의 흐름의 일부분을 실행하고 나서 다른 프로세스들로 순서를 바꾸어 실행하는 동안 선점된다(일시적으로 정지된다). 이 프로세스들 중에서 하나의 문맥에서 실행되는 프로그램은 순간 마치 프로세서를 배타적으로 소유한 것처럼 보인다.

이렇게 중간에 프로세스의 동작이 멈춰도 문제는 없다. 프로세서가 정지할 때마다 프로그램의 메모리 위치나 레지스터 내용에 변경되는 사항 없이 프로그램 실행은 순차적으로 다시 실행되며, 실행되는 프로세스가 달라지면 컨텍스트 스위칭이라는 과정을 거쳐 번갈아 여러 프로세스가 수행되도 문제가 없게 된다.

프로세스는 Private 주소 공간을 갖는다.

프로세스는 각 프로그램에 자신이 시스템의 주소공간을 혼자서 사용한다는 착각을 불러일으킨다. 프로세스는 각 프로그램에 자신만의 사적 주소 공간을 제공한다. 이 공간의 특정 주소에 연결된 메모리의 한 개의 바이트가 일반적으로 다른 프로세스에 의해서는 읽혀지거나 쓰여질 수 없다.

비록 각각의 사적 주소공간에 연결된 메모리의 내용이 일반적으로 서로 다를지라도 각각의 이런 공간은 동일한 일반적인 구조를 갖는다.

그림 2. 프로세스 주소 공간

예를 들어 위의 그림은 x86 프로세스에 대한 주소공간의 구조를 보여준다. 주소 공간의 아랫부분은 텍스트, 데이터, 힙, 스택 세그먼트를 갖는 사용자 프로그램을 위해 예약된다. 이와 같은 프로세스의 주소공간 구조는 모든 프로세스가 공유하게 된다는 점을 기억하자. 이러한 공간들은 가상 메모리 체계에 의해서 관리된다.

동시성 흐름

논리 흐름은 컴퓨터 시스템 내에서 여러 가지 형태를 가지며, 예외 핸들러, 프로세스, 시그널 핸들러, 쓰레드, 자바 프로세스 등이 이러한 논리흐름의 예이다.

이 중 자신의 실행 시간이 다른 흐름과 겹치는 논리흐름은 동시성 흐름이라고 부르게 된다. 좀 더 엄밀히 말해서 만일 Y가 시작해서  Y가 완전히 종료되기 이전에 X가 시작되고, 또 다시 X가 종료되기 이전에 Y가 다시 한 번이라도 시작이 된다면 이를 동시성 흐름이라고 할 수 있다. 

이처럼 프로세스가 다른 프로세스들과 교대로 실행되는 것을 멀티태스킹이라고 하며, 한 프로세스가 자신의 흐름 중 일부를 실행하는 매시간 주기는 타임 슬라이스라고 부른다.

앞서 살펴본 동시성 흐름의 경우에는 흐름이 돌아가는 프로세스 코어나 컴퓨터의 개수에 무관하다. 만약 두 흐름이 시간상 중첩된다면, 이들이 동일한 프로세서에서 돌아가더라도 이들은 동시적이다.

그렇지만 병렬 흐름이라고 알려진 동시성 흐름의 부분집합을 구별하는 것이 필요하다. 만일 두 개의 흐름이 서로 다른 프로세서 코어나 컴퓨터에서 동시에 돌아가고 있다면 이는 병렬 흐름(parrallel flow)이라고 부르게 된다.

Init process (pid = 1)

각각의 프로세스는 공유한 id로 식별이 가능하다. 프로세는 파일 디렉토리와 같은 계층적인 구조를 가지고 있으며 자식과 부모 관계를 갖는다. 그렇게 따라 올라간 프로세스 트리의 꼭대기에는 하나의 제어 프로세스가 존재하는데 해당 프로세스는 init 프로세스라고 불리며, 궁극적으로 모든 시스템과 사용자 프로세스의 조상으로 정의된다.