운영체제 학습 노트 목차

CPU 스케줄링 — 누구를 언제 올릴까

CPU 코어는 한 순간에 하나만 실행하는데, 실행하고 싶은 프로세스·스레드는 수백 개다. 그럼 누구를 골라, 얼마나 오래 CPU에 올릴까? 이 결정을 내리는 게 스케줄러다. 스케줄러의 고민은 영원한 줄다리기다 — 모두에게 공평하면서, 응답이 빠르고, 전체 처리량도 높여야 한다. 이 세 목표가 서로 당기는 걸 어떻게 절충하는지를 본다.

양보하느냐 빼앗느냐 — 선점과 비선점

먼저 근본적인 갈림길이다. 비선점(non-preemptive) 스케줄링은 — 한 번 CPU를 잡은 프로세스가 스스로 양보하거나(I/O 대기·종료) 끝날 때까지 계속 쓴다. 단순하지만, 욕심 많은 한 프로세스가 CPU를 독차지하면 나머지가 굶는다. **선점(preemptive)**은 — OS가 타이머 인터럽트로 강제로 CPU를 회수해 다른 프로세스에 넘긴다. 그래서 한 프로세스가 CPU를 붙잡고 안 놔도 일정 시간 뒤 강제 전환된다 — 현대 OS는 거의 다 선점형이다(응답성을 위해).

가장 공평한 출발 — 라운드로빈

선점의 가장 단순한 형태가 라운드로빈이다 — 모두에게 *같은 시간 조각(타임 퀀텀)*을 주고 차례로 돌린다. A가 10ms 쓰면 B로, B가 10ms 쓰면 C로… 다시 A로. 완벽히 공평하고 굶는 프로세스가 없다. 다만 퀀텀 크기가 트레이드오프다 — 퀀텀이 짧으면 응답은 빠르지만(자주 돌아오니) 컨텍스트 스위치가 잦아 오버헤드가 크고, 퀀텀이 길면 스위치는 줄지만 응답이 느려진다. 02·03편에서 본 컨텍스트 스위치 비용이 여기서 다시 등장한다 — 너무 자주 전환하면 일보다 전환에 시간을 쓴다.

중요한 걸 먼저 — 우선순위와 그 함정

모든 작업이 똑같이 중요하진 않다. 우선순위 스케줄링중요한 작업을 먼저 실행한다. 그런데 위험한 함정이 있다 — **기아(starvation)**다. 낮은 우선순위 작업은, 높은 우선순위 작업이 계속 들어오면 영원히 차례가 안 온다. 그래서 오래 기다린 작업의 우선순위를 점점 올려 주는 **에이징(aging)**으로 보완한다. (이 기아는 락·자원 경쟁 등 동시성 전반에 나타나는 문제다.)

행동을 보고 정한다 — MLFQ

더 영리한 스케줄러는 — 작업의 성격을 미리 모르니, 행동을 관찰해 정한다. **MLFQ(다단계 피드백 큐)**는 여러 우선순위 큐를 두고, 작업의 행동에 따라 큐를 옮긴다.

다이어그램 로딩 중…

핵심 아이디어는 — 어떤 작업이 퀀텀을 다 쓰면(CPU 집약적) 우선순위를 낮추고, 퀀텀을 다 쓰기 전에 I/O로 양보하면(I/O 집약적·대화형) 높은 우선순위를 유지한다는 것이다. (출처: MLFQ.) 그래서 타이핑·클릭 같은 대화형 작업은 즉각 반응하고(높은 우선순위·짧은 퀀텀), 무거운 계산은 뒤에서 길게 돈다 — 응답성과 처리량을 동시에 잡는다. 기아를 막으려 주기적으로 모두를 높은 큐로 부스트한다.

비율로 공평하게 — 리눅스 CFS

리눅스는 또 다른 길을 간다 — **CFS(Completely Fair Scheduler)**는 고정 타임 슬라이스를 버리고, 각 프로세스에게 CPU의 공평한 비율을 주려 한다. 각 프로세스가 *얼마나 CPU를 썼는지(vruntime)*를 추적해, 가장 적게 쓴 프로세스를 다음에 올린다 — "지금까지 가장 손해 본 사람 먼저"라는 발상이다. (출처: Linux CFS.) *우선순위(nice 값)*는 이 비율에 가중치로 반영된다.

왜 알아야 하나 — 이 CPU 집약 vs I/O 집약 구분은 스레드 풀 크기를 정할 때도 그대로 쓰인다 — CPU 바운드면 코어 수만큼, I/O 바운드면(대기가 많으니) 더 크게. MLFQ가 I/O 집약 작업에 높은 우선순위를 주는 것처럼, 작업의 성격에 따라 다르게 대접하는 게 효율의 핵심이다. 그리고 퀀텀이 짧으면 스위치 오버헤드라는 교훈은 — 실행 단위를 너무 많이 만들면 컨텍스트 스위칭으로 느려진다는 것과 같은 뿌리다. 스케줄링은 결국 *"비싼 CPU와 전환 비용을, 공평·응답·처리량 사이에서 어떻게 나누나"*의 문제다.

정리하면, 스케줄러는 하나뿐인 CPU를 수많은 작업에 나눠 주며공평·응답성·처리량을 절충한다. 선점으로 한 작업의 독점을 막고, 라운드로빈으로 공평하게 돌리되 퀀텀 크기로 응답성↔스위치 비용을 저울질하며, 우선순위로 중요한 걸 먼저 하되 에이징으로 기아를 막고, MLFQ행동을 관찰해 대화형·계산형을 다르게 대접하고, CFS는 *공평한 비율(vruntime)*로 나눈다. 이 작업들이 CPU를 두고 경쟁하다 보면 — 공유 자원을 동시에 건드리는 위험이 생긴다. 그게 다음 편, 동시성이다.

스레드 — 공유·전환 비용·유저/커널·가상 스레드동시성 — 경쟁 조건·뮤텍스/세마포어·CAS