프로세스(process)는 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램을 의미한다.
프로세스 내부에는 최소 하나의 스레드(thread)를 가지고있는데, 실제로는 스레드(thread)단위로 스케줄링이 이뤄진다.
하드디스크에 있는 프로그램을 실행하면, 실행을 위해서 메모리 할당이 이루어지고, 할당된 메모리 공간으로 바이너리 코드가 올라가게 된다. 이 순간부터 프로세스라 불린다.
- Code 영역 : 프로그램을 실행시키는 실행 파일 내의 명령어(소스코드)
- Data 영역 : 전역변수, static 변수
- Heap 영역 : 동적할당을 위한 메모리 영역.
- C언어 : malloc & free // C++ : new & delete // JAVA : new 등
- Stack 영역 : 지역변수, 함수 호출시 전달되는 인자(파라미터)를 위한 메모리 영역.
프로세스의 상태는 프로세스가 실행됨에 따라 달라진다.
- New : 프로세스가 처음 생성된 상태
- Ready : 프로세스가 CPU에 할당되기를 기다리는 상태 (메모리 등 다른 조건을 모두 만족하고)
- Running : 프로세스가 할당되어 CPU를 잡고 명령을 수행 중인 상태
- Waiting : 프로세스가 어떠한 이벤트가 발생하기를 기다리는 상태. CPU를 할당해도 당장 명령을 수행할 수 없는 상태.
- Terminated : 프로세스가 실행을 마쳤을 때. 아직 완전히 프로세스가 제거되진 않은 상태.
Ready, Waiting 상태의 프로세스는 실행중인 것은 아니지만 메인 메모리에 올라와 있어야 한다.
하지만 긴 시간동안 대기해야해서 대기 시간동안 메모리 사용이 불필요하거나 메모리에 너무 많은 프로세스가 올라가 있는 경우, 프로세스가 Suspended Ready(중단된 준비)나 Suspended Waiting(중단된 대기) 상태로 변할 수 있다. 혹은 부모가 자식을 중단 상태로 만들 수도 있다.
Waiting 상태와 유사하지만 차이가 있는데, Waiting은 자신이 요청한 이벤트가 만족되면 Ready 상태로 돌아가지만, Suspended는 외부에서 다시 시작을 해주어야 활성화가 된다.
따라서 이를 반영한 프로세스의 상태표는 다음과 같다.
PCB(Process Control Block)는 운영체제가 각 프로세스를 관리하기 위해 프로세스별로 보유하고 있는 자신의 정보 묶음이다. 커널의 주소 공간에 있으며 다음의 구성 요소를 갖는다.
-
운영체제가 관리상 사용하는 정보
- Process state
- Process ID
- Scheduling information : 프로세스의 중요도, 스케줄링 큐 포인터 등 스케줄링 파라미터 정보
- Priority : 프로세스의 우선순위
-
CPU 수행 관련 하드웨어 값
- Program counter : 해당 프로세스가 이어서 실행해야 할 명령의 주소를 가리키는 포인터
- Register : 프로세스가 인터럽트 이후 올바르게 작업을 이어가기 위해 참조하는 CPU 레지스터 값
-
메모리 관련
- Code, Data, Stack의 위치 정보, base/limit 레지스터 값
-
파일 관련
- open file descriptors : 열린 파일 목록
-
이전 프로세스의 상태 레지스터 내용을 보관하고 다른 프로세스의 레지스터를 적제하여 프로세스를 교환하는 과정이다.
-
운영체제는 CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장하고, CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어온다.
-
즉, CPU입장에서 Context는 PCB이기 때문에 PCB 정보가 바뀌는 것이 Context Switch라고 볼 수 있다.
-
다만, 시스템 콜이나 인터럽트가 발생한다고 반드시 Context Switch가 일어나는 건 아니다. 다른 프로세스에 프로세서가 넘어가야 Context Switch이다.
**멀티프로그래밍(Multiprogramming)**의 목적은 CPU를 최대한 사용하기 위해 몇몇 프로세스를 항상 실행시키는 것이다. **시간 공유(Time Sharing)**의 목적은 프로세스 간에 CPU를 빠르게 전환함으로써 사용자가 각 프로그램이 실행되는 동안 서로 상호작용할 수 있도록 만드는 것이다.
이러한 목적을 달성하기 위해 프로세스 스케줄러는 CPU에서 프로그램 실행을 위해 사용 가능한 프로세스를 선택한다. 이렇게 어떤 프로세스를 프로세서에 할당할 것인가를 결정하는 일을 프로세스 스케줄링(Process Scheduling)이라고 한다.
프로세서가 하나인 시스템은 오직 하나의 running 프로세스를 가질 수 있고, 여러 프로세스가 존재하는 경우 나머지는 CPU가 free 상태가 될 때까지 기다려야 하기 때문에 적절한 프로세스 스케줄링이 필요하다.
프로세스를 스케줄링하기 위한 큐(Queue)로는 Job Queue, Ready Queue, Device Queue가 있다. 프로세스가 이 큐들을 이용하여 수행된다.
Job Queue는 하드디스크에 있는 프로그램이 실행되기 위해 메인 메모리의 할당 순서를 기다리는 큐이다. Ready Queue는 현재 메모리 내에 있으면서 CPU를 잡아서 실행되기를 기다리는 프로세스의 집합이다. 그리고 Device Queue는 I/O 장치를 기다리는 프로세스의 집합이다.
스케줄러의 종류로는 다음과 같은 3가지가 있다.
-
시작 프로세스 중 어떤 프로세스를 Ready Queue로 보낼지를 결정하며, 프로세스에 메모리 및 각종 자원을 할당한다. 자주 발생하지는 않는다. 또 Degree of Multiprogramming(메모리에 몇 개의 프로세스가 존재하는지)를 제어한다.
-
Time-sharing 시스템에서는 보통 Long-Term Scheduler가 존재하지 않고 무조건 Ready Queue로 올라가는 방식이다.
- 어떤 프로세스를 다음에 실행시킬지를 선택하며, 프로세스에 CPU를 할당한다. 자주 발생하는 작업이므로 충분히 빨라야 한다.
-
프로세스를 수행하다가 메모리에서 잠시 제거했다가, 시간이 지난 후 다시 메모리에 넣고 수행을 이어나가는 것이 더 이득이 될 수 있는 경우가 존재할 수 있다.
-
이를 위해 프로세스를 통째로 메모리에서 디스크로 쫓아내서 여유 공간을 마련하는 작업을 Swapping이라고 한다. 즉, 프로세스에게서 메모리를 빼앗는 것이다. 이 작업을 Medium-Term Scheduler가 수행한다.
-
메모리를 빼앗긴 프로세스는 위에서 봤던 중단된(sudpended) 상태의 프로세스가 된다.