※ 본 카테고리의 내용은 부스트캠프 챌린지 기간동안 학습한 내용을 바탕으로 정리한 내용입니다.
목차
0. 프로세스 스케줄링?
프로세스 스케줄링을 이해하기 위해서는 먼저 프로세스와 스케줄링에 대한 이해가 필요합니다.
프로세스(Process)는 운영체제(OS)에서 메모리 영역을 할당받아 실행되는 독립적인 프로그램을 뜻합니다.
그리고 우리가 앞으로 어떤 일을 할 지 결정하는 것을 스케줄을 짠다고 하죠?
컴퓨터의 스케줄링(Scheduling)은 앞으로 할 일(프로세스)을 처리하기 위해서 CPU 등의 자원배정을 하는 것을 말합니다.
그 배정을 누가 하냐?! 바로 운영체제(OS)가 하는 것이죠!
이 운영체제는 자신이 담당하는 CPU 코어(스레드)에게 앞으로 어떤 일을 할 지를 정해주는 역할을 합니다.
스케줄링을 알았다면 프로세스 스케줄링을 이해하는 것은 그다지 어렵지 않습니다!
프로세스 스케줄링(Process Scheduling)은 준비 상태에 있는 프로세스들 가운데서 CPU를 사용할 프로세스를 선택하는 것을 말합니다.
준비 상태가 뭐냐구요..?
제가 그린 못생긴(?) 상태전이도를 보면서 이야기 해 봅시다!
상태전이도는 프로세스의 상태변화를 나타내는 그림입니다.
위 상태전이표에서 준비 상태는 CPU가 프로세스를 처리하기 직전에 대기좌석에 앉아있는 상태라고 보시면 됩니다.
그럼 대기 상태랑 무슨 차이가 있는지 궁금해 하실 수 있습니다.
대기 상태는 실행을 하다가 어떤 이벤트가 발생해서 중간에 멈춘 경우에 위치하는 곳입니다.
콘서트로 이야기하면, 준비 상태는 무대 뒤에서 기다리고 있는 상태이고, 대기 상태는 무대에 나왔는데 특정 상황으로 인해 잠시 의자에 앉아있는 상태라고 볼 수 있습니다.
실행 상태는 말 그대로 실행하고 있는 상태이고, 완료 상태는 처리가 끝난 상태를 의미합니다.
생성 상태는 준비 상태로 가기 전에 보조기억장치에서 주기억장치로 처리할 프로세스를 이동하는 과정이라고 생각하시면 됩니다.
이런 상태 대신 자료구조의 Queue를 본따서 준비큐(ready queue), 대기큐(Device queue) 등으로 부르기도 합니다.
- 생성 : 프로세스를 처리하기 위해 보조기억장치에서 주기억장치로 꺼내오는 상태
- 준비 : CPU에 할당받기 위해 기다리고 있는 상태
- 대기 : CPU에서 작업을 하다가 특정 I/O event로 인해 작업을 멈춘 상태
- 실행 : CPU에서 작업중인 상태
- 완료 : CPU에서 작업을 완료한 상태
그리고 준비에서 실행, 실행에서 대기, 실행에서 완료, 대기에서 준비로 가는 등의 상태변화를 상태 전이(Context Switching)라고 부릅니다.
이런 과정을 통해 프로세스 스케줄링이 이루어지고, CPU는 프로세스를 수행하는 것이죠.
1. 스케줄링 기법
그렇다면 같은 상태에 있다면 어떤 프로세스가 먼저 처리될까요?
이것이 스케줄링에 있어서 가장 핵심이 되는 기술입니다.
스케줄링 기법은 정말로 다양한데, FCFS, SJF, SRT, RR 등이 대표적인 스케줄링 기법입니다.
기법을 설명하기 전에 한 가지 먼저 알아야 할 것이 바로 선점형 / 비선점형 방식의 차이입니다.
선점형(Preemptive Scheduling)은 높은 우선순위를 가지는 프로세스는 항상 먼저 스케줄되어야 하고, 커널 안에서 프로세스의 순위는 지속적으로 변합니다.
즉 CPU가 어떤 작업을 하고 있더라도 높은 우선순위를 가지는 프로세스가 준비 상태로 들어오게 되면 새로 들어온 프로세스를 수행하게 됩니다.
반면 비선점형(Non-Preemptive Scheduling)은 높은 우선순위를 가지는 프로세스라고 할 지라도 이미 수행되고 있는 스케줄링을 밀어낼 수 없는 방식입니다.
1.0. FCFS
FCFS(First Come First Served)는 먼저 CPU를 요청하는 프로세스를 먼저 처리하는 방식입니다.
FIFO와 똑같은 논리입니다. 먼저 들어오면 먼저 처리해야한다는 것이죠.
Process | Burst Time |
P1 | 15 |
P2 | 4 |
P3 | 5 |
P4 | 1 |
이 방식의 단점은 바로 대기 시간이 길다는 것입니다.
먼저 들어온 프로세스를 완료하는 데 걸리는 시간이 길다면 당연히 기다리는 프로세스도 많아지겠죠?
하지만 이 기다림은 모두에게 공평해서 아무리 짧은 일이라도 앞에 있는 긴 일이 끝나기 전에는 수행할 수 없습니다.
합리적이지만, 뒤에 있는 프로세스 입장에서는 복장이 터질 노릇일겁니다.
1.1. SJF / SRT
SJF(Shortest Job First) 방식은 가장 짧은 프로세스를 먼저 스케줄링 하는 방식입니다.
이 방식은 선점형(Shortest Remaining Time First)과 비선점형(Shortest Job First)으로 나눠지는데,
선점형의 경우 프로세스를 수행하다가도 더 짧은 프로세스가 들어온다면 그것을 먼저 수행하고,
비선점형은 이미 수행중이라면 더 짧은 프로세스가 들어와도 계속 수행한다는 차이점이 있습니다.
Process | Burst Time |
P1 | 6 |
P2 | 8 |
P3 | 7 |
P4 | 3 |
Process | Burst Time | Arrival Time |
P1 | 6 | 0 |
P2 | 8 | 14 |
P3 | 7 | 7 |
P4 | 3 | 2 |
1.2. RR
RR(Round Robin) 방식은 정해진 time-quantum 만큼만 준비큐 안에 있는 프로세스끼리 돌아가며 수행하는 방식입니다.
나름 공평한 방식이지만, time-quantum을 너무 짧게 한다면 잦은 context switch로 인해 동작 시간에 손해를 볼 수 있습니다.
Process | Burst Time |
P1 | 24 |
P2 | 3 |
P3 | 3 |
2. 스레드
스레드(Thread)는 프로세스를 좀 더 구체화한 개념으로, 하나의 프로세스 내에서 실행되는 흐름의 단위를 뜻합니다.
보통 하나의 프로그램은 하나의 프로세스를 가지고 있지만, 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있습니다.
이것을 멀티 스레드라고 부릅니다.
만약 스레드 시스템이 없다면, 작업을 하면서 동시에 시간이 흐르게 할 수 없기 때문에 매번 작업이 끝날 때마다 시간을 새로 맞춰줘야 하지만, 우리의 OS는 멀티스레드 환경에서 돌아가고 있기 때문에 하나의 CPU에서 여러 스레드를 동시에 처리함으로써 문제 없이 시간이 흐르면서 작업이 가능하게 된 것이죠.
(흔히 4코어 8스레드, 6코어 12스레드라고 부르는 것도 이와 같은 맥락입니다. 하지만 멀티 스레드 스케줄링을 통해 1코어 1스레드 컴퓨터에서도 프로세스를 진행해도 시간이 멈추지 않고 흐를 수 있게 된 것이죠!)
2.0. 멀티 프로세스 & 멀티 스레드
멀티 스레드는 하나의 프로세스 안에서 분기로 갈라진 요소입니다.
따라서 하나의 프로세스이기 때문에 얻을 수 있는 장점과 단점을 모두 가지게 됩니다.
먼저 멀티 프로세스는 여러 프로세스 중 하나에 문제가 발생해도 그 프로세스만 죽고 다른 프로세스에는 영향을 끼치지 않는다는 장점이 있습니다.
하지만 Context Switching하는 과정에서 많은 시간이 소모되는 등의 오버헤드가 발생하게 됩니다.
반면 멀티 스레드는 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 통신 속도가 빠르고 정보를 공유하기 쉽습니다. (그렇다고 Context Switching 과정이 생략되는 것은 아닙니다!)
또한 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들기 떄문에 자원을 효율적으로 관리할 수 있죠.
대신 하나의 스레드에 문제가 발생하면 전체 프로세스가 영향을 받게 됩니다.
3. 공유 자원 관리
멀티 프로세스, 멀티 스레드처럼 동시에 여러 작업을 수행할 때 가장 중요한 것은 "공유자원을 어떻게 관리하느냐" 입니다.
만약 A 스레드에서 a=10이라는 변수를 만들고 이 변수에 20을 추가로 더해준다고 생각해봅시다.
그런데 그 사이에 B 스레드에서 a=20을 선언해 버린다면 어떻게 될까요?
A 스레드에서 20을 더하고 결과를 출력하면 40이라는 엉뚱한 값이 나오게 되겠죠?
이처럼 공유 자원을 안전하게 관리하기 위해서는 상호 배제를 확실하게 해야합니다.
멀티 스레드가 공용 리소스에 접근하는 방식으로 가장 대표적인 Mutex와 Semaphore에 대해서 가장 흔히 알려져있는 화장실 예제를 통해 알아보겠습니다.
먼저 Mutex는 공유된 자원의 데이터에는 단 하나의 프로세스 혹은 스레드만 접근이 가능한 방식입니다.
키가 하나뿐인 유일한 화장실이라고 생각하면 됩니다.
만약 어떤 사람이 키를 들고 화장실로 들어갔다면, 다른 사람은 키가 없어서 그 화장실에 접근할 수 없겠죠?
다음 사람은 먼저 화장실로 들어간 사람이 키를 들고 나올 때까지 그 데이터에 접근하지 못하게 됩니다.
이걸 컴퓨터에 대입하면 현재 권한을 가진 스레드 혹은 프로세스만이 그 데이터에 접근해서 지지고 볶고 할 수 있다는 이야기가 됩니다.
Semaphore는 공통으로 관리하는 하나의 값을 이용하여 상호 배제를 달성하는 방법입니다.
화장실이 총 3개가 있을 때, 옆에 사용 가능한 화장실의 수를 적어두었다고 생각해봅시다.
만약 3명의 사람들이 각각 하나의 방에 들어간다면 다음 사람은 더 이상 화장실에 들어갈 수 없겠죠?
이걸 컴퓨터에 대입하면 공유자원에 변수만큼의 스레드 혹은 프로세스만이 데이터에 접근할 수 있는 것이죠.
최근댓글