이화여자대학교 컴퓨터공학과 반효경 교수님의 "운영체제 (KOCW)" 강의를 필기한 내용입니다.
다소 잘못된 내용과 구어적 표현 이 포함되어 있을 수 있습니다.
문서를 이전하는 과정에서, 이미지 데이터가 유실되어 문서상에 보이지 않습니다.
CPU, IO Burst
(사진 사라짐)
- 프로세스가 실행되는 것은 (일반적으로) CPU 를 연속적으로 사용하다가 IO 때문에 Block 되있거나 하는 것의 반복이라고 할 수 있는데 이때
- CPU 를 연속적을 사용하는 구간을 CPU Burst 라고 하고
- IO 때문에 Block 먹어있는 구간을 IO Burst 라고 한다
CPU, IO Bound Job
(사진 사라짐)
- 이 그래프는 한 CPU Burst 의 실행시간과 CPU Burst 의 빈도를 나타낸 그래프인데
- 보면 왼쪽은 CPU Burst 의 기간이 아주 짧고 빠르게 반복된다
- 이것은 잦은 IO 에 의해 CPU Burst 와 IO Burst 가 빈번하게 반복되는경우인데
- 이러한 Job (== Process) 들을 IO Bound Job 이라고 한다
- 일반적으로 IO 는 표준 입출력 등의 사람과 Interaction 하기 위한 것이 많기 때문에 사람과의 interaction 이 잦은 경우에 IO Bound Job 이 된다
- 그리고 오른쪽의 Job 들은 한번 CPU 가 잡으면 오랫동안 사용하여 CPU Burst 의 기간이 길고 따라서 빈도는 낮아지는데 (당연히 한번 잡았을때 길게 쓰니까 빈도는 작아질 수 밖에 없다)
- 이러한 Job 들을 CPU Bound Job 이라고 부르고 일반적으로 연구 등의 목적을 위해 복잡한 계산을 오랫동안 진행하는 Job 들인 경우가 많다
- 뭐 그래서 IO Bound Job 이 사람과의 상호작용이 잦기 때문에 CPU Bound Job 이 너무 CPU 를 오래 잡고 있어 사용자 Response 가 늦어지는 일이 벌어지지 않게 하기 위해 CPU Scheduling 을 한다네
Scheduler, Dispatcher
- CPU Scheduler: Ready 인 프로세스 중에 Running 상태가 될 프로세스를 고르는 커널 프로세스
- CPU Scheduling 이 발생하는 경우는 대표적으로 다음과 같다
- 프로세스가 CPU Time 을 _자진 반납_하는 경우 (Non-preemptive)
- IO 등의 사유로 CPU Time 을 반납 (Running → Blocked)
- Process Terminate 로 CPU 반납 (Running → Exit)
- 프로세스가 CPU Time 을 빼앗기는 경우 (Preemptive)
- Timer interrupt (Running → Ready)
- IO 가 완료된 프로세스의 우선순위가 현재 프로세스보다 높을 때 (Blocked → Ready)
- 프로세스가 CPU Time 을 _자진 반납_하는 경우 (Non-preemptive)
- CPU Scheduling 이 발생하는 경우는 대표적으로 다음과 같다
- Dispatcher: 현재의 프로세스에서 CPU Scheduler 가 고른 프로세스로 Context switch 를 진행하는 커널 프로세스
CPU Scheduling
고려사항들
- Ready 상태인 (CPU Burst 에 진입한) 프로세스 중 누구한테 CPU 를 줄 것인가?
- 한번 CPU 를 받았으면 끝날때까지 계속 쓰게 할 것인가 아니면 중간에 뺏을 것인가?
Performance Index (Measure, Criteria)
- Performance Index 는 성능을 측정하는 척도를 의미하는데 아래와 같이 두개로 나눌 수 있다
- System Performance: 얼마나 시스템의 자원을 효율적으로 굴리느냐
- CPU Utilization: 얘는 CPU 이용률을 의미한다
- “률” 이기 때문에 당연히 전체에서 부분이 차지하는 비율을 의미하는데
- CPU Utilization 에서는 “시간” 을 기준으로 측정한다 → 즉, 시스템이 작동하고 있는 전체 시간 중에서 CPU 가 일을 하고 있는 비율이 얼마냐
- Throughput: 얘는 처리량을 의미하는데
- CPU Utilization 이 시간에 대한 값이었다면 얘는 양을 나타내는 값이다
- 즉, 단위시간동안 처리한 작업의 양을 의미하는 것
- CPU Utilization: 얘는 CPU 이용률을 의미한다
- Program Performance: 사용자가 느끼는 프로세스의 빠릿빠릿함
- Turnaround Time: 한번의 CPU Burst 동안 걸린 시간의 총합
- Waiting Time: 한번의 CPU Burst 동안 CPU 가 할당되지 않고 기다린 시간의 총합
- Response Time: 한번의 CPU Burst 동안 CPU 가 처음으로 할당되기까지 걸린 시간
- 그냥 이렇게만 보면 멍게소리인가 싶을텐데 한번의 CPU Burst 에 어떤 일들이 일어나는지를 생각해보면 알기 쉽다
- 먼저 IO Burst 가 끝나고 CPU Burst 에 들어온 시간이 0초라고 해보라
- 그러고 바로 CPU 를 할당받을 수 있으면 기모찌하겠지만 인생이란게 그렇게 녹록하지 않아서 4초에 CPU 를 할당받아서 작업을 했다라고 치면
- 첫 4초가 Response Time 이 되는 것
- 즉, CPU Burst 가 시작된 이래로 얼마나 빨리 CPU 가 할당되었느냐 이다
- 그리고 만일 Preemptive 로 스케줄링되어 6초에 CPU 를 빼앗겼다가 7초에 다시 받고 10초에 IO 가 생겨서 IO Burst 로 빠져나갔다고 치면
- 일단 기다린 시간을 다 합쳐보면 맨 처음 4초에 중간에 1초 기다렸으니까 5초 → 이게 Waiting Time 이 된다.
- 즉, Waiting Time 은 처음의 Response Time에다가 CPU Burst 중간중간에 쉬는시간까지 다 합친 값이다
- 그리고 전체적으로는 10초가 걸렸으므로 이게 Turnaround Time 이 된다
- 즉, Turnaround Time 은 IO Burst 사이의 시간 간격이라고 생각할 수도 있고
- Waiting Time 에다가 CPU Time 까지 합친 시간이라고 생각할 수도 있다
스케줄링 알고리즘 분류
- Preemptive: 하나의 프로세스가 너무 오래 CPU 를 차지하지 못하도록 중간에 뺏는 알고리즘
- Non-preemptive: 하나의 프로세스가 CPU 를 먹으면 IO 등의 이슈가 없는 한 계속 들고 있게 하는 알고리즘
Priority Scheduling
- 그냥 단순하게 생각해서 우선순위에 따라 다음 프로세스를 선택하는 방식인데
- Preemptive 의 경우에는 당연히 우선순위가 높은 놈이 들어오면 빼앗고 Non-preemptive 의 경우에는 높은놈이 들어와도 빼앗지 않았다가 그놈이 끝나면 그 다음 우선순위 높은놈에게 주는 방식
- 주의할 점은 일반적으로 UNIX(Linux) 계열에서는 숫자가 낮을수록 우선순위가 높은 거다
- Syslog 생각해봐도
emerg
가 0 이잖여
- Syslog 생각해봐도
Starvation, Aging
- 이후에 등장하는 스케줄링 알고리즘에서 Starvation 이라는 말이 나오는데 이건 알고리즘의 부작용으로 특정 프로세스가 CPU 를 할당받지 못하는 상황을 의미한다
- 만일 우선순위가 낮은 프로세스의 경우 해당 프로세스보다 우선순위가 높은 프로세스가 항상 존재한하면 해당 프로세스는 영원히 CPU 를 받지 못한다.
- 이를 해결하기 위한 방법으로 Aging 이 있는데 이건 우선순위가 낮은 프로세스가 오랫동안 CPU 를 할당받지 못하면 자연스럽게 우선순위가 높아지게 하는 방법을 의미한다
Scheduling Algorithms
FCFS (First Come First Serve)
-
뭐 별거 없다 → 선입선출
- 당연히 무지성 선입선출이기 때문에 Non-preemptive 이다
-
얘의 문제점은 예상하시는 바와 같이 앞에 오래걸리는 놈이 하나 버티고 있으면 그 뒤에 있는 놈들은 다 지연된다는 거다
-
예를 들어 아래의 두개 상황을 비교해봐라
(사진 사라짐)
- 첫번째의 경우는 앞에 오래걸리는 애가 있어서 평균 Waiting Time 이 17이나 되지만
- 만일 앞에 짧은 애가 오면 평균 Waiting Time 은 3으로 거의 1/6 이 줄어든다
- 이렇듯 FCFS 에서 앞에 오래걸리는 한놈때문에 나머지가 전부 지연되는 것을 Convoy effect 라고 하더라
SJF (Shortest Job First) 혹은 SPN (Shortest Process Next)
-
FCFS 를 보면서 ‘그럼 제일 적게걸리는 놈한테 먼저 주면 되는거 아닌가’ 라고 생각했으면 이게 그거다
-
즉, CPU Time 이 제일 적은 놈에게 우선적으로 CPU 를 주는 것
-
얘는 이제 Non-preemptive 하고 Preemptive 두가지 버전이 있는데
-
Non-preemptive SJF 은 일단 CPU 를 CPU Time 이 적은놈한테 주되 이걸 빼앗을 수는 없으므로 더 짧은 놈이 들어와도 일단은 현상유지하는 것이고
-
Preemptive SJF 는 CPU Time 이 더 짧은 놈이 오면 CPU 를 빼앗아서 이놈한테 주는거다
- 그런데 이때 CPU Time 은 지금 실행중인 놈의 남은 시간과 새로운 놈의 시간을 비교하기 때문에 SRTF (Shortest Remaining Time First 혹은 그냥 SRT) 라고도 부른다
- 또한 이 경우는 평균 Waiting Time 이 최소가 되는 것으로 알려저 있다 (Waiting Time Optimal)
- 똑똑이들이 증명해놨다네
-
뭐 아주 좋아보이지만 아쉽게도 얘도 문제가 있다
- Starvation: 눈치챘겠지만 앞에 짧은 애들만 오면 긴놈은 절대로 CPU 를 받을 수 없다.
- 그리고 CPU Time 는 사전에 알지 못하는 값이다
-
CPU Time 을 예측하는 방법으로 Exponential Averaging 이라는게 있는데 다른 분야에도 등장하는 개념이라니까 간단하게 짚고 넘어가면
t(n)
은 n 번째의 CPU Time 이고따우(n)
은 n 번째의 CPU Time 예측값일때- Exponential Averaging 의 공식은 다음과 같다
(사진 사라짐)
- 이 식을 전개해보면
(사진 사라짐)
- 가 되는데 상수
a
가0 < a && a < 1
이기 때문에 제곱할수록 작아진다 - 즉, 제일 최근의 값은 1에 그나마 가까우므로 가중치가 높아지고 옛것으로 갈수록 0에 가까워지니까 가중치가 낮아지는 것으로도 생각할 수 있는 것
- 찾아보니까 이 개념은 머신러닝에서도 사용되는듯
RR (Round Robin)
- 지겹다 지겨워 그냥
- 알다시피 무지성 돌라돌라골림판이다
- 즉, 일정한 Time Quantum 으로 CPU Time 을 난도질해서 해당 시간이 끝나면 다른 프로세스에게 또 Time Quantum 만큼의 CPU Time 만 주는 방법이다
- 얘는 다양한 CPU Time 을 가지는 프로세스들이 섞여있을 때 맛집이 된다
- 스케줄링 할 때 CPU Time 을 예측할 필요도 없고
- CPU Time 크든 작든 돌아가며 CPU 가 할당되므로 Starvation 에 빠질 우려도 없다
- 심지어 CPU Time 길수록 Waiting Time 도 늘어나는 합리성까지 보여준다
- 하지만 CPU Time 이 전부 똑같을때는 똥된다
- 단순히 FCFS 를 생각해도 100 짜리 4개가 들어오면 100, 200, 300, 400 의 시간에 프로세스가 종료되지만
- RR 로 돌리면 다같이 돌다가 전부 400에 프로세스가 종료되기 때문
- 이렇듯 CPU Time 이 같은 경우에는 비효율적이나 일반적인 상황이 아니기 때문에 대부분 효율적이다
- Time Quantum 이 극단적이 되면 어찌되는가
q
가 너무 커지면 FSFC 와 다를바가 없어서 비효율적이고q
가 너무 작아지면 Context Switching 의 오버헤드가 너무 커져 비효율적이 된다
Multi-level Process Queueing
- 위에 소개된 알고리즘들은 전부 프로세스를 큐 하나에 때려박고 적당히 꺼내서 CPU 를 할당해주는 방식이었다면
- 지금부터 소개되는 알고리즘들은 프로세스를 우선순위에 따라 여러 큐에 넣어서 관리하는 방법들이다
- 이러한 방식은 일반적으로 큐마다 다른 스케줄링 알고리즘을 사용하고
- 상위 우선순위의 큐가 비지 않아 Starvation 이 발생할 것을 방지하기 위해 CPU 를 차등 분배한다
- 즉, 상위 우선순위의 큐가 비어야만 하위 큐로 가는게 아니고
- 우선순위가 높은 큐에는 CPU 를 더 많이 할당해주고 낮은 큐에는 적게 할당하는 식으로 유도리있게
Multi-level Queue
(사진 사라짐)
- 얘는 프로세스의 특성에 따라 우선순위를 두고 우선순위에 따른 큐를 여러개 만들어 상위 우선순위의 큐가 비어야 그 아래 큐에 있는 프로세스에게 CPU 가 할당될 수 있도록 하는 Preemptive 한 방식이다
- 위 그림은 그렇게 여러개의 큐를 나누어놓은 예시 그림임
- 하지만 이러한 방식은 우선순위 변동의 유연함이 없어 문제가 있더라
Multi-level Feedback Queue (Feedback Scheduling)
(사진 사라짐)
- 얘는 RR 방식의 큐를 여러개 준비해놓고 아래로 내려갈수록 Quantum 값이 증가하게 해놓은 다음
- 처음 들어온 프로세스는 제일 우선순위가 높은 큐에 넣고
- Quantum 내에 끝내지 못하면 그 아래 큐로 내려보내는 방식이다
- 이 방식은 SJF 알고리즘에서 CPU Time 을 알 수 없다는 단점을 해결했다고 볼 수 있는데 왜냐면
- 일단 처음에는 CPU Time 을 알 수 없으니까 Quantum 을 짧게 하는 대신 우선순위를 높여주고
- 해당 Quantum 내에 끝내지 못했다면 Quantum 을 좀 더 오래 가져가는 대신 우선순위가 낮아지게 함으로써
- 자연스럽게 빨리 끝나는 프로세스는 우선순위가 높아지고 오래걸리는 프로세스는 우선순위가 낮아지는 효과를 볼 수 있다
그 외의 여러가지 CPU Scheduling 방식들
Multi-processor Scheduling
- 프로세스들이 고만고만한 경우 (Homogeneous): 하나의 큐에 다 때려넣고 여러개의 CPU 들이 나눠먹거나
- 반드시 특정 CPU 에서만 실행되어야 하는 경우에는 걔를 위해 CPU 하나를 할당해주고 나머지를 나눠먹거나
- CPU 부하 분산 (Load Sharing): 놀고 있는 CPU 가 없도록 하기 위해 공동 큐를 두거나 CPU 마다 큐를 구성
- Symmetric Multiprocessing: CPU 들이 동등한 자격으로 스스로 스케줄링 하는 방식
- Asymmetric Multiprocessing: 얘는 마스터를 선출하는거마냥 스케줄링 작업을 전담하는 CPU 를 하나 선출해서 나머지는 이놈이 스케줄링한거에 그냥 따르는 방식
Real Time Scheduling
- 일반적으로 Real Time 이라고 하면 주어진 시간 내로 반드시 종료되야 하는 것을 의미하는데
- Hard Real Time: 말 그대로 → 시간 내에 반드시 끝나야 함
- Soft Real Time: 얘는 시간 내에 끝나야 하긴 하지만 그렇지 못한다고 해서 큰 문제가 생기지 않는 경우를 의미하는데
- 그냥 일반적인 스케줄링에서 우선순위를 좀 높여주는 방식으로 해결 가능하고
- 동영상 재생이 대표적인 예시다 → 1초에 24프레임 이상을 로드해야되지만 그렇지 못했다고 해서 지구멸망은 아닌
Thread Scheduling
- User Thread 의 경우: Local Scheduling 이라고 부르는데 OS 는 이 쓰레드의 존재를 모르기 때문에 POSIX Thread 같은 라이브러리들이 직접 해준다
- Kernel Thread 의 경우: Global Scheduling 이라고 부르는데 Short-term scheduler 가 프로세스 스케줄링하는것과 동일하게 해준다
Algorithm Evaluation
-
Queueing Model: 아래 그림처럼 입력 데이터(Arrival Rate) 를 확률분포로 주고 이때의 출력(Service Rate) 를 이용해 성능을 측정
- 다분히 이론적이어서 많이는 사용하지 않는댄다
(사진 사라짐)
-
Implementation & Measurement: 실제로 코드를 작성해 커널을 빌드하여 성능 측정
-
Simulation: 커널 전체가 아닌 해당 알고리즘만 코드로 작성해 실제 OS에서의 작동 방식을 분석해 만든 입력 데이터 (Trace) 를 이용한 방법