CPU Scheduling
scheduling을 하기 위해서는 한 memory 안의 여러 개의 프로그램 중 누구에게 CPU를 할당할 것인지 결정하는 것이 필요하다.
일반적으로 program을 하게 되면
CPU와 I/O burst가 교환되는 process인 경우, 어떻게 CPU를 주는 것이 효율적인 scheduling 방법일지 고려해야 한다.
한정된 CPU time을 여러 process가 효율적으로 공유할지 생각하는 것이다.
program이 실행되기 시작하면 짧은 I/O burst time을 갖고 있는 I/O bound process의 개수가 초반에 많고 I/O를 사용하는 시간들이 길어질수록 빈도수가 낮아지게 되며, CPU burst는 짧게 많이 가지고 있다.
Process가 수행될 때, 끝날 때까지 CPU Scheduling이 필요한 경우
1. running에서 waiting 상태로 바뀔 때
이 때에는 wait 되는 process가 자발적으로(non-preemptive) CPU를 넘긴다. 어떠한 event가 끝날 때까지 기다리기 위해 block을 시키는 것이다. CPU는 다른 process에게 할당된다.
2. running에서 ready 상태로 바뀔 때
각각의 process에는 time quantum이 주어진다. 자기가 사용할 수 있는 주어진 CPU time이 끝나게 되면 context switch가 일어난다. 이럴 때에는 OS가 interrupt를 발생시켜 CPU를 뺏어와야 한다(preemptive). 그리고 다른 process에게 CPU를 할당한다.
3. 자기가 기다리던 event가 끝나서 waiting에서 ready로 바뀔 때
다른 곳에서 CPU를 뺏어서 이 process에게 할당되기까지 기다려야 한다.(preemptive)
4. 종료될 때
종료될 때에는 CPU가 자동적으로 다른 곳에 할당된다.(non-preemptive)
Preemptive와 non-Preemptive인 경우에 생각해봐야 할 것들
앞서 CPU를 자발적으로 내놓는지의 여부에 따라 나누었는데 preemptive인 경우 특히 고려해야 할 것들이 있다.
1. 공유영역 "Shared data"
공유 data를 사용할 때 preemptive인 경우, 예를 들어 process A와 B가 공유 영역에 무엇인가 쓴다고 하자.
A가 쓰고 있는 도중에 CPU를 뺏겼다면, 그리고 그 때 B가 같은 영역에 data를 쓴다면 A와 B의 data가 섞일 수 있다.
그래서 preemptive한 scheduling의 경우 공유 data인 경우 동기화를 어떻게 해 주어야 할 지 고려해야 한다.
하지만 non-preemptive한 경우에는 자발적으로 CPU를 포기하게 되는 것이기에 preemptive한 경우보다 동기화의 문제가 상대적으로 덜 심각하다.(non-preemptive인 경우에도 공유 memory인 경우에는 주의가 필요하다)
2. Kernel data, 공유 data의 경우
kernel mode에서 preemption을 고려해야 한다.
예를 들어 process A가 어떤 kernel service를 요구한다.
다른 kernel process가 생길 수 있다. 두 개의 kernel process가 같은 device driver나 혹은 kernel 상의 data structure를 수정할 경우 이 때 문제가 생길 수 있다. 이 kernel process 끼리 동기화가 필요하다. user process끼리 뿐만 아니라 preemptive인 경우엔 kernel process의 동기화가 필요하다.
그러나 이 때에도 여러 문제가 나타날 수 있는데 locking과 같은 여러 메커니즘에 의해 생길 수 있다. 이것을 단순화 시키기 위해 kernel process를 non-preemptive하게 구성할 수 있다.
즉, kernel process가 자발적으로 CPU를 내놓을 때까지, 내놓으면 CPU scheduling이 발생하도록 만드는 것이다.
ex) I/O call이 완료되거나 자신의 I/O를 발생시켰을 때 그 I/O call이 끝나거나 하면 scheduling이 발생하도록
-> 그런데 이렇게 해결한다면 I/O가 끝날 때까지 CPU가 switch되지 않고 I/O가 끝날 때까지 CPU가 기다려야 하는 상황이 발생한다. 특히 real-time process인 경우에 overhead가 상당히 커지게 된다. 그렇게 되면 response time(어떤 작업이 처음 실행되기까지 걸린 시간)이 굉장히 느려지게 될 수 있다.
그래서 preemptive하게 적절하게 구성을 하되, user process뿐 아니라 kernel process 사이에서도 동기화를 해 주어야 한다.
3. OS activities, 즉 interrupt
interrupt가 발생했을 경우 interrupt handler가 수행된다. 한 kernel process가 interrupt handler를 수행하게 될 때, preemptive하다면 이 도중에 CPU가 다른 process에게 전달될 수도 있다.
문제는 그렇게 되면 interrupt를 수행하기 위해 수정된 정보들이 미완성으로 끝날 수 있다는 것이다.
그리고 다른 process가 또 같은 data structure를 수정할 수 있기 때문에 정보들이 엉킬 수 있다.
그래서 3번째로 고려해야할 점은 interrupt는 이렇게 엉키는 것을 해제하는 것이다.
일반적으로 interrupt handler에 들어가기 전에 다른 interrupt가 발생하지 않도록 disable을 시켜준다. 그리고 interrupt handler를 다 처리한 후에 enable을 하는 것으로 해결한다. 일종의 locking machanizm이다.
주의할 점은 진입점을 disable하는 것이지 interrupt 자체를 disable하는 것이 아니라는 것.
Scheduling을 하기 위한 기준
크게 5가지가 존재한다.
- CPU utilization - keep the CPU as busy as possible
- 단위 시간당 사용되는 CPU 활용도
- 이 활용도를 높여주는 것이 좋다. 최대 한도로 사용할 수 있도록 scheduling algorithm을 부여해야 한다.
- Throughput
- 단위 시간당 처리량, 최대가 되도록 하는 것이 좋다.
- Turnaround time
- process가 start해서 끝날 때 까지의 시간
- Waiting time
- ready queue 안에서 기다리는 시간
- Response time
- 첫 번째 result가 생성될 때까지의 시간
- turnaround time과는 다른데, turnaround time은 모든 result가 나와서 끝날 때까지의 시간이고 response time은 첫 result가 나올 때까지의 시간이다.
- interactive system의 경우에 이러한 response time이 굉장히 중요하다고 한다.
'운영체제' 카테고리의 다른 글
RPC_Remote Procedure Calls (0) | 2022.08.12 |
---|---|
(IPC) Interprocess Communication이 필요한 이유 (0) | 2022.08.05 |
Process Scheduling (0) | 2022.07.29 |
Semaphores (0) | 2022.07.21 |