프로세스란?
프로세스란 간단히 말하면, 실행중에 있는 프로그램을 의미한다.
스케줄링의 대상이 되는 작업(task)과 같은 의미
프로세스 내부에는 최소 하나의 스레드를 갖고있다.
프로그램을 실행하면, 실행을 위해 메모리 할당이 이뤄지고 할당된 메모리 공간으로 바이너리 코드가 올라가는데 이 순간부터 프로세스라 불린다.
프로세스의 메모리 구조
💡 각 프로세스 당 하나의 메모리를 가짐
Code: 프로그램을 실행시키는 명령어들의 영역
Data: 전역변수, static 변수의 영역
Heap: 동적할당을 위한 메모리 영역(프로그래머가 필요할 때 사용하는 영역)
Stack: 지역변수, 파라미터를 위한 영역
프로세스 상태
생성(create): 프로세스가 생성중인 상태
실행(running): 프로세스가 프로세서를 차지하여 명령어들이 실행중인 상태
준비(ready): 프로세스가 프로세서를 사용하고 있지는 않지만, Ready Queue에서 언제든지 사요할 수 있는 상태로, CPU가 할당되기를 기다린다.
대기(waiting): 프로세스가 I/O 완료, 시그널 수신 등의 어떤 이벤트를 기다리고 있는 상태
종료(terminated): 프로세스의 실행 종료
프로세스 스케줄링
💡 프로세스 스케줄링은 다음 네 가지 경우에 일어날 수 있다.
실행 상태(running)에서 대기 상태(waiting)으로 전환될 때
실행 상태(running)에서 준비 상태(ready)으로 전환될 때
대기 상태(waiting)에서 준비 상태(ready)으로 전환될 때
종료되었을 때(terminated)
☑️ 선점(preemptive)과 비선점(non-preemptive)
프로세스 스케줄링이 첫 번째와 네 번째 경우에만 일어난다면, 비선점(non-preemptive, 또는 cooperative) 스케줄링이라 한다.
비선점 스케줄링 시스템에서는 프로세스가 대기 상태에 들어가거나 종료되지 않고서는 프로세스 전환이 일어나지 않는다.
프로세스 스케줄링이 위의 네 가지 경우 모두에서 일어나면, 선점(preemptive) 스케줄링이라 한다.
선점 스케줄링 시스템에서는 운영체제가 프로세스에 할당되었던 CPU를 자체적으로 판단하여 뺏어올 수 있다.
즉, 선점 스케줄링은 운영체제가 CPU를 먼저 '선점(먼저 차지)'하여 필요하다면 CPU를 프로세스로부터 뺏을 수 있는 스케줄링 방법이고 비선점은 반대이다.
이 둘의 효율성은 상황에 따라 다르기 때문에, 뭐가 더 효율적인지 판단은 불가하다.
-> 어떤 시스템에서는 선점 스케줄링을 구현하기 위해 필요한 하드웨어(ex. 타이머)가 없어 어쩔 수 없이 비선점 스케줄링을 사용할 수 밖에 없다.
-> 선점 시스템에서는 프로세스 가 ㄴ공유 자원에 대한 문제가 발생할 수 있다. 만약 한 프로세스가 자원을 사용한 샅애(ex. 한 파일을 읽고 있을 때)에서 프로세스 전환이 일어나서 다른 프로세스가 running 상태가 되었는데, 이 두 번째 프로세스도 같은 자원에 접근하면 문제가 발생한다.
☑️ 스케줄링 알고리즘 효율
💡 각 알고리즘들의 효용성을 따지는 기준에는 크게 다섯가지가 있다.
CPU 이용률: 전체 시스템 시간 중, CPU가 작업을 처리하는 시간의 비율
처리율: 단위시간당 얼마나 많은 프로세스들이 완료되는지
소요시간: 프로세스가 요청된 후 완료하기까지의 걸리는 시간, 메모리 접근 시간, 대기 큐에서의 대기 시간, CPU에서의 실행 시간, I/O 시간 등의 합으로 계산된다.
대기 시간: 프로세스가 대기 큐에서 기다리는 시간의 합
반응 시간: 프로세스가 요청된 후 첫 번째 응답을 받기까지 걸리는 시간. 주로 상호교환 시스템에서 사용된다.
☑️ 스케줄링 알고리즘 종류
FCFS 스케줄링 (First Come First Serve Scheduling): FCFS 스케줄링은 CPU를 먼저 요청한 프로세스가 먼저 CPU를 배정받는 스케줄링 방법. 비선점 스케줄링 방식이며 큐(Queue)를 이용하면 쉽게 구현 가능.
아래 표와 같이 CPU 한차례 사용시간(CPU burst time)을 갖는 프로세스 P1,P2,P3가 순서대로 들어왔다.
이때 CPU 스케줄링의 결과는 아래와 같다.
FCFS 스케줄링은 구현은 간단하지만, 효율적이지 않다.
위의 그림처럼 프로세스들의 평균 대기 시간(average waiting time)을 계산해보면
-> P1: 실행까지 대기시간: 0ms
-> P2: 실행까지 대기시간: 24ms
-> P3: 실행까지 대기시간: 27ms
-> 평균 대기 시간 = (0+24+27)/3 =17 ms
만약 P2,P3,P1 순서대로 프로세스들이 들어왔다면?
-> P1: 실행까지 대기시간: 6ms
-> P2: 실행까지 대기시간: 0ms
-> P3: 실행까지 대기시간: 3ms
-> 평균 대기 시간 = (6+0+3)/3 =3 ms
이렇듯 FCFS 스케줄링은 프로세스가 들어오는 순서에 따라서만 결과가 바뀌기 때문에 그닥 효율적이지 못하다.
이렇게 다른 모든 프로세스들이 커다란 한 프로세스가 끝날때까지 기다리는 현상을 convoy effect라고 한다.
FCFS 스케줄링을 기반으로 하여 CPU를 할당하되, 각 프로세스는 한 번에 쓸 수 있는 CPU 시간 크기(시간 할당량)가 지나면 시간 종료 인터럽트에 의해 CPU를 뺏기게 되는 방식
주로 우선순위 스케줄링과 결합하여 프로세스의 시간 할당량을 조절하는 방식으로 활용한다.
FCFS에서 프로세스 하나가 CPU를 독점하는 단점을 방지하지만, Context Switch의 오버헤드를 감수해야한다.
SJF 스케줄링 (Shortest Job First Scheduling)
FCFS 스케줄링처럼 convoy effect 현상이 나타나는 것은 매우 비효율적이다.
이를 줄이기 위해서는? CPU 한차례 사용시간이 작은 프로세스부터 먼저 끝낸다면 convoy effect를 최소화할 수 있을 것인데, 이를 SJF 스케줄링이라고 한다.
SJF는 선점 스케줄링일 수도 있고, 비선점 스케줄링일 수도 있다.
비선점 SJF 스케줄링에서는 프로세스가 실행되는 도중 더 작은 CPU 한차례 사용시간을 가지는 프로세스가 들어오더라도, 실행되던 프로세스가 스스로 대기 상태(waiting)또는 종료 상태(terminated)가 되기 전에는 context 전환이 일어나지 않는다.
하지만, 선점 SJF 스케줄링에서는 문맥 전환이 일어난다.
선점 SJF 스케줄링은 SRTF 스케줄링 (Shortest Remaining Time First Scheduling)이라고도 한다.
비선점 SJF 스케줄링
1) 0ms에 프로세스 p1이 들어와서 20ms만큼의 작업을 한다.
2) 3ms에 P2가 들어오지만 비선점이므로 계속해서 P1이 작업을 한다.
3) P3가 5ms에 들어오고, 작업시간이 P2보다 짧으므로 P3를 먼저 작업시킨다.
4) 결과적으로 P1의 대기시간은 0ms, P3는 (20-5)=15, P2는 (25-3)=22 가 된다.
5) 따라서 평균 대기시간은 (0+15+22)/3 = 12.333이다.
FCFS 스케줄링보다 시스템 효율성이 좋아보이긴 하지만, 실제로 사용하기는 힘들다.
-> 운영체제가 프로세스의 종료 시간을 정확하게 예측하기 어려움
-> p1도 작업을 해야하는데 계속해서 p1보다 작업 시간이 적은 프로세스들이 들어온다면 p1은 작업이 불가하다.