
프로세스(Process)란?
프로세스(Process)는 쉽게 말해서 실행중인 프로그램이다.
예를 들어 리그오브레전드 게임을 다운을 받으면 프로그램상태로 내 컴퓨터의 디스크에 저장이된다. 이를 실행하게 되면 메모리에 로드되게 되는데, 이때 프로세스가 되는 것이다.
즉 프로세스는 실행 중인 프로그램으로 디스크로부터 메모리에 적재되어 CPU의 할당을 받을 수 있는 것을 말한다.
또한 프로그램이 여러 프로세스가 될 수 있다.
프로세스 상태(Process State)
프로세스는 상태를 가지고 있고 상태가 계속 변한다.
프로세스 상태는 다음과 같다.
- new : 프로세스가 생성되기 전 상태(아직 프로세스가 아님)
- ready : 메모리에 Load되어 CPU 할당받을 준비가 되어있는 상태
- running : CPU에 의해서 명령어가 실행되고 있는 상태
- waiting : CPU를 할당받을 준비가 안되어있고 I/O 작업이나 다른 이벤트가 일어나는 것을 기다리는 상태
- terminated : 프로세스가 종료된 상태(더 이상 프로세스가 아님)
하나의 CPU 코어만 있다고 가정한다면, CPU 코어는 1개 당 하나의 프로세스만 running할 수 있다.
그리고 그 외의 프로세스는 전부 waiting, ready 상태에 있다고 말할 수 있다. (1, 5번은 프로세스 상태로 보기 어렵기 떄문)
그러면 프로세스 상태는 어떻게 변하게 될까? 바로 아래에 설명하겠다.
프로세스 스케쥴링(Process Scheduling)
메모리에는 많은 프로세스들이 올라와 있는데 프로세스들은 어떤 순서로 CPU 할당이 되고 I/O 작업이 이루어 질까?
바로 운영체제의 프로세스 스케쥴링이라는 방식을 이용해 이루어진다.
운영체제는 이를 위해 Scheduling Queue를 사용하는데 Ready Queue와 Waiting Queue가 있다.
Ready Queue는 ready 상태의 프로세스를 담는 큐이다.
그러면 어떤 방식으로 Queue에 저장될까? 그냥 먼저들어온 순서대로 맨 앞에 배치시킬까?
방식은 여러가지가 있고 이것을 결정하는 것은 CPU Scheduler인데 이는 다음에 포스팅을 할 예정이다.
다시 본론으로 돌아와서, Ready Queue에 있는 프로세스 중 CPU 스케쥴러에 의해 CPU를 할당을 받은 프로세스는 ready상태에서 running 상태로 변하게 되는데 이 과정을 Scheduler Dispatch라고 한다.
그리고 running 상태인 프로세스가 interrupt에 걸려 ready 상태가 되어 다시 ready queue에 돌아갈 수도 있다.
프로세스가 running 상태에 있다가 I/O 작업을 요청하게 되면, 프로세스는 running 상태에서 waiting 상태가 되고 이 프로세스가 I/O 작업을 하게되는 동안 다른 프로세스가 running 된다.
Waiting Queue(= Block Queue, I/O Queue)는 이때 I/O 작업을 기다리는 프로세스의 큐이다.
I/O 장치들마다 I/O request가 다르기 때문에 보통 장치마다 waiting queue를 따로 두어 관리한다.
그리고 I/O 작업이 끝나면 아래의 그림처럼 waiting 상태에 있던 프로세스가 ready 상태로 변하고 ready queue로 다시 넘어가게 된다.
CPU는 한 프로세스가 종료될 때 까지 작업을 하는것이 아니라는 것을 알 수 있다. 그러면 어떻게 한 프로세스가 running -> waiting -> ready -> running 상태를 거칠 때 CPU는 어디까지 작업했는지 어떻게 알 수 있을까? 바로 프로세스 문맥에 이러한 정보들이 저장되어 있기때문이다. 바로 아래에 설명하겠다.
문맥(Process Context)
운영체제에서 문맥이란 CPU가 프로세스를 실행하면서 필요한 내용들로, 프로세스 중단 시에 보존되고 다시 복구되어야 하는 프로세스의 모든 실행 정보를 말한다.
문맥은 크게 하드웨어 문맥, 프로세스의 주소 공간, 프로세스 관련 커널 자료 구조 등이 있다.
하드웨어 문맥
CPU의 수행 상태를 나타내는 정보로, Program Counter(PC)와 Register들을 말한다.
PC는 프로세스의 어디까지 수행했는지 나타내는 값이고 Register는 CPU가 프로세스의 명령어를 수행하면서 사용했던 데이터, 연산 결과값등을 가르킨다.
프로세스의 주소 공간
프로세스들은 Code, Data, Stack, Heap 영역의 주소 공간을 가진다.
- 스택 영역: 함수의 매개변수, 복귀 주소와 로컬 변수와 같은 임시 자료를 가진다.
- 데이터 영역: 전역 변수를 수록한다.
- 힙 영역: 프로세스 실행 중에 동적으로 할당되는 메모리이다.
- 코드 영역: 실행할 코드와 매크로 상수가 기계어의 형태로 저장된 공간이다. 컴파일 타임에 결정되고 중간에 코드를 바꿀 수 없게 Read-Only로 지정되어 있다.
즉 CPU는 프로세스를 실행하면서 어떤 함수를 호출했고 리턴해야 하는지, Data는 어떤 값으로 변했는지 등을 알아야 한다.
프로세스 관련 커널 자료 구조
운영체제는 프로세스를 관리하기 위해 커널에 프로세스의 자료 구조를 저장하는데, PCB와 Kernel stack등이 있다.
Kernel Stack이란?
사용자 프로세스에서 OS 고유 기능을 실행하기 위해 시스템 콜을 하면 CPU의 PC가 커널 코드를 가르키고 이 명령어를 실행하게 된다.
커널도 프로그램이고 함수로 이루어져 있어 어떤 프로세스가 커널의 어떤 함수를 호출했는지가 담겨 있는 곳이 커널 스택이다.
Context Switch(문맥 교환)
운영체제가 다른 프로세스를 dispatch할 때, 즉 CPU를 다른 프로세스의 문맥을 저장해야 한다.
위 그림처럼 P0을 실행시키다가 PCB에 문맥을 저장하고 완료되면 P1의 PCB에 저장된 문맥을 불러와 이어서 작업하는 과정을 Context Switch라고 한다.
쉽게 말해 백업 과정이라고 생각하면 된다.
문맥 교환하는 시간에는 CPU가 일을 하지 못하여 오버헤드가 생긴다. 이를 Context Switch Overhead라고 부른다.
오버헤드는 필요한 것보다 더 많은 일을 하는 것이라고 생각하면 된다.
'그러면 하나의 프로세스를 끝날때까지 기다리면되지!' 라고 생각이 들거다. 만약에 우리의 운영체제가 이러한 방식을 채택한다고 해보면, CPU의 이용률도 떨어지고 우리가 유튜브로 노래를 틀면서 Word 작업을 하지 못할 것이다. 즉 사용감이 현저히 낮아 질 것이다.
그래서 문맥 교환의 오버헤드가 들더라도 멀티태스킹 방식을 사용하는 것이다.
이번 포스팅을 하면서 간단하게 프로세스가 무엇인지 공부해 볼 수 있었고, 아주 보람찬 시간이였다.
끝.