초기시절 컴퓨터들은 한번에 한개의 프로그램이 실행되는 환경을 제공해 주었다. 즉, 한개의 프로그램은 시스템의 모든 자원을 독점하였다. 사람은 한번에 한가지 일을 빠르고 확실하게 처리하고 다른일을 하는것이 효율적일지 몰라도 컴퓨터의 cpu는 매우(?) 빠르기 때문에 이는 낭비이다. 오늘날 컴퓨터 시스템은 여러개의 프로그램이 메모리에 로딩되고 동시에!실행되는 환경을 유지하고 있다. 이러한 환경을 제공해 주기 위하여 등장하는 것이 바로 프로세스(process)라는 개념이다.
프로세스란? 간단히 정의내리면 현재 실행중인 프로그램을 의미하게 된다. 이것은 시분할 시스템의 기본 단위이기도 하다. 결국 동시에 어떤 프로그램을 실행시킨다는 것은 시간적으로 여러개의 프로세스를 돌아가면서 실행시키는 것으로 구현하게 되는 것이다. 극단적으로 결국 하나의 씨피유를 가지고는 진정한 의미의 멀티 프로세싱이 불가능하다.
프로세스라는 개념은 오에스차원에서 매우 중요하다. 유저가 원하고자 실행시키는 프로그램 밑 바닥에는 마치 평온한 호수가에서 유유자적하는 어플 프로세스들이 발바닥을 촐싹거리면서 휘어져야 한다. 결국 시스템은 각종 프로세서들의 모음으로 이루어진다고 할 수 있다. 또한 프로세스란 리소스를 점유한채 실행중인 코드 를 의미한다.
프로세스를 이루고 있는 구성 요소들은 실로 다양하다. 먼저 다음번 코드를 실행시킬 코드가 들어있는 주소를 가리키고 있는 프로그램 카운터, 다른 참조해야할 레지스터들의 값, 잠시 필요한 값을 저장해 두는 스택, 데이터, 그리고 전역변수 등등이 있다. 프로그램 그 자체와 프로세스와의 가장 중요한 차이점은 프로그램 자체는 수동적 존재임에 반해 프로세스는 위의 정보를 바탕으로 살아 움직이는 능동적인 존재라는 점이다. 따라서 프로세스는 나름대로의 상태를 가지고 있다. 총 다섯가지 상태로 크게 나뉘게 되고 각 상태에 대한 흐름도는 책을 찾아보기 바란다.
프로세스는 같은 프로그램에 귀속될지라도 서로 독립적으로 존재하게 되는데, 그 좋은 심플텍스트와 같은 어플리케션이다. 이러한 프로그램 자체는 하나만 존재하지만, 여러개의 창을 열때마다 각각의 프로세스들이 생성되어서 각각의 윈도우를 관리해 주게 된다. 이 때 좀더 전문적으로 얘기하면 , 각각의 프로세스의 텍스트 섹션은 동일하지만 데이터 섹션은 다르다! 라고 말할 수 있다.
또 프로세스의 중요한 특징은, 이놈이 살아 꿈틀대는 것만으로도 모자라 이제는 아들, 딸 프로세스 까지 생성이 가능하다는 데에 있다. 무슨말이냐... 한개의 프로세스는 위에서 말한 각종 정보를 가지고 태어나는데, 이녀석이 차일드 프로세스를 만들게 되면 부모프로세스의 데이터 및 스트럭쳐들이 모조리 복사되어 똑같은 붕어빵 프로세스가 태어나게 된다. 이때 생성을 가한 프로세스를 패런트프로세스, 생성된 프로세스를 차일드 프로세스 라고 한다.
이들 사이의 관계에서는 엄격하면서도 유용한 구석이 있다. 먼저 차일드 프로세스는 글로벌이건 로컬이건 간에 가리지 않고 패런트로부터 모조리 데이터를 복사해 오는데, 복사된 순간부터는 각자의 길을 걷게 된다. 로컬 변슈야 그냥 그러려니 해도 나중에 패런트 프로세스의 글로벌 변수를 고쳐 주어도 차일드는 그냥 씹어버린다. 자신에게 이미 글로벌 복사본이 존재하기 대문이다. 그러면 이러한 두 부자지간의 세대차이를 어떻게 극복해야 하나 하는 문자가 대두 되는데, 이를 해결해 주는 것이 바로 IPC(inter process Communication) 이다.
자, 이젠 다시 프로세스 고유의 성격을 논해보기로 하자. 프로세스를 논하기 위해서는 먼저 PCB(Process Control Block)을 알아야한다. 각각의 프로세스는 PCB로 대표되어 지는데 이는 프로세스의 상태, 프로그램 카운터, 씨피유 레지스터, 씨피유 스케줄링 정보, 메모리 관리 정보, 어카운팅 정보, 그리고 I/O 상태 정보등을 담고 있게 된다. 거대한 레코드 같은 존재이다. 그러나 하나의 프로세스를 하나의 PCB로 표현할 수 있다는 사실은 프로세스 간의 관계를 정의하고 나타내기 위해서는 매우 유용한 개념이다.
먼저 프로세스 스케줄링은 멀티프로그래밍의 목적(언제나 활성화되어 있는 프로세스들이 존재함으로써 cpu가 놀지 않고 그 활용도를 극대화 시키는 것)에 걸맞도록 설계 되어야 한다.
스케줄링을 위해서는 언제나 큐(queue)가 필요하다. 참고로 큐란 FIFO(First In First Out)를 구현하는 데이터 스트럭쳐 이다. 먼저 온놈이 먼저 나간다는 아이디어다. 한개의 프로세스가 시스템에서 생성이되면, 일단 잡큐(job queue)에 쇽, 들어가게 된다. 잡큐에 있던 녀석들이 메모리에 로딩되고 실행할 준비를 마치면 비로서 레디큐(ready queue)로 다시 쇽쇽 들어가는데, 레디큐는 링크드 리스트로 이루어져 있다. 즉, PCB로 링크드 리스트를 만드는 것이다. 이 밖에 필요한 큐로서는 I/O와 관련된 프로세스를 담아주는 디바이스큐( device queue)라는 것이 또 존재한다. 각각의 디바이스는 각자의 디바이스큐를 가지고 있게 된다.
이제 멀티프로그래밍이 구현되는 원리를 살펴보도록 하자. 시스템이 p0라는 프로세스를 실행하고 있다고 하자. 그런데 불현듯 p1을 위한 인터럽트나 시스템 콜이 호출되어 버리면, 오에스는 즉시 p0의 PCB 내부 필드의 값들을 모두 업데이트 시킨다음 상태를 레디상태로 돌려버리고 레디큐에 쑤셔 넣는다. 그대신 p1의 PCB를 런닝상태로 전환시키고 필요한 값들을 씨피유의 레지스터에 주르륵 펼쳐놓고 작업을 하게 된다. 같은 방법으로 다시 p0는 씨피유의 복귀되고 p1은 쫒겨나고 ... 이런식으로 순간순간 여러개의 프로세스들이 자신의 상태를 바꾸어가며 질서있게 각자의 큐에서 씨피유의 호출을 기다리는 것이다.
이렇게 레디큐에서 기다리는 프로세스들중 어떤 녀석을 씨피유에 불러들이는 과정을 디스패치(dispatched)되었다! 라고 말하는 것이고, 도데체 어떤 프로세스를 어느 때에 디스패치 시킬것인가를 결정하는 알고리즘을 프로세스 스케줄링 알고리즘이라고 한다. 프로세스 스케줄러(구현된 스케줄링 알고리즘)는 또 크게 두가지로 나누는데 첫째는 롱텀 스케줄러(long-term scheduler)또는 잡스케줄러(job scheduler) 라고 일컫는다. 이 녀석은 생성될 프로세스중 어떤 것을 메모리에 로드 시킬것인가를 결정한다.
또 다른 하나는 숏텀 스케쥴러(short-term scheduler)또는 씨피유 스케줄러(cpu-scheduler)라고 하며 이 녀석이 바로 레디큐에서 어떤것을 디스패치 시킬 것인가를 결정하게 된다.
이들의 가장 큰 차이점은 결정의 빈도에 있다고 할 수 있는데, 숏텀스케줄러가 당연히 롱텀 스케줄러보다 빈도수가 많다.
프로세스 스케줄링 논할 때 롱텀과 숏텀 스케줄링 이렇게 두개 만을 여기서는 소개했지만, 원래는 한개를 더 갖다 붙이기도 한다. 바로 미드텀(mit-term)스케줄링이다. 미드텀 스케줄링은 이미 메모리에 존재하는 프로세스중 몇가지를 제거해 줌으로써 멀티 프로그래밍의 정도, 즉 씨피유의 및 메모리의 부하를 줄이는데 사용되는 기법이다. 이를 다른말로는 스와핑(swapping)이라고도 한다. 이는 메모리 스케줄링에서도 등장하는 말인데 메모리에 프로세스를 올리는 스왑인(swap in), 메모리에서 프로세스를 제거하는(완전히 지우는 것이 아니라하드디스크 같은 기억장치에 보관을 하게됨)스왑 아웃(swap out)등이 있다. 여기서 한가지 느낄 수 있는 사실은 메모리 스케줄링을 잘 하면 결국 프로세스 스케줄링 또한 효율적으로 이루어진다는 것이다.
씨피유가 한 프로세스를 실행하다가 실행하던 프로세스의 상태를 저장하고 또 다른 프로세스로 순간적으로 전환해서 실행을 하는것이 멀티프로그래밍의 원리라는 사실을 이젠 깨달았을 것이다. 이 때 멋진 단어가 하나 등장한다. 바로 '컨텍스트 스위칭(context switching)'이다. 컨텍스트 스위칭이란 바로 씨피유가 그렇게 프로세스를 전환하는 순간을 일컫는 말이다. 문제는 이것이 정말 순수한 오버헤드라는 사실이다. 멀티 프로그래밍을 구현하기 위하여, 본래의 프로세스들의 내용과는 관계없이 그냥 이루어지는 것이기 때문이다. 이는 오에스 자체보다는 하드웨어적인 환경에 더욱 영향을 많이 받게 된다. 이 컨텍스트 스위칭은 한 시스템의 성능을 평가함에 있어서 병목현상의 주된 원인이 되기도 한다. 그래서 이제는 프로세스들끼리는 필연적으로 컨텍스트 스위칭을 필요로 한다는 사실을 극복하려는 과정에서 태어난 것이 바로 쓰레드(thread)이다. 쓰레드에 대한 설명은 차후에 하도록 하고 일단, 왜 멀티 쓰레딩이 빠른 성능을 보여주는 지에 대한 기본적인 이해가 되었으리라 본다. 바로 컨텍스트 스위칭이 없기 때문이다.
다음장에서는 구체적으로 어떻게 패런트 및 차일드 프로세스를 생성, 이용, 종료 하는지 알아보도록 하자.