본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 28. · 4 Views
CPU 스케줄링 기초 완벽 가이드
운영체제의 핵심인 CPU 스케줄링을 초급 개발자도 이해할 수 있도록 쉽게 설명합니다. 선점형과 비선점형의 차이부터 다양한 성능 지표까지, 실무에서 꼭 알아야 할 개념을 다룹니다.
목차
1. CPU 스케줄링이란
어느 날 김개발 씨가 컴퓨터 앞에서 여러 프로그램을 동시에 실행하고 있었습니다. 웹 브라우저, 음악 플레이어, 코드 에디터가 모두 부드럽게 돌아가는 것을 보며 문득 궁금해졌습니다.
"CPU는 하나인데 어떻게 여러 프로그램이 동시에 돌아가는 거지?"
CPU 스케줄링은 한마디로 여러 프로세스 중 누가 CPU를 사용할지 결정하는 것입니다. 마치 놀이공원에서 놀이기구를 타기 위해 줄을 서는 것과 같습니다.
스케줄러가 줄을 관리하며 누가 먼저 탈지 정해주는 역할을 합니다. 이것을 제대로 이해하면 시스템 성능이 어떻게 결정되는지 알 수 있습니다.
다음 코드를 살펴봅시다.
# CPU 스케줄러의 기본 구조
class CPUScheduler:
def __init__(self):
self.ready_queue = [] # 실행 대기 중인 프로세스들
self.current_process = None # 현재 CPU를 사용 중인 프로세스
def add_process(self, process):
# 새 프로세스가 도착하면 준비 큐에 추가
self.ready_queue.append(process)
def select_next_process(self):
# 핵심: 다음에 실행할 프로세스를 선택
if self.ready_queue:
self.current_process = self.ready_queue.pop(0)
return self.current_process
return None
김개발 씨는 입사 3개월 차 주니어 개발자입니다. 오늘도 열심히 코드를 작성하던 중, 자신의 프로그램이 가끔 멈칫거리는 현상을 발견했습니다.
분명히 빠른 컴퓨터인데 왜 이런 일이 생기는 걸까요? 선배 개발자 박시니어 씨가 다가와 상황을 살펴봅니다.
"아, 이건 CPU 스케줄링과 관련이 있어요. 운영체제가 어떻게 프로세스들을 관리하는지 알면 이해가 될 거예요." 그렇다면 CPU 스케줄링이란 정확히 무엇일까요?
쉽게 비유하자면, CPU 스케줄링은 마치 은행 창구와 같습니다. 은행에는 창구가 하나뿐인데 고객은 여러 명입니다.
은행 직원은 누가 먼저 서비스를 받을지 순서를 정해야 합니다. 먼저 온 사람이 먼저 받을 수도 있고, 급한 업무가 있는 사람이 먼저 받을 수도 있습니다.
CPU 스케줄링도 마찬가지로 여러 프로세스 중 누가 CPU라는 귀한 자원을 사용할지 결정합니다. CPU 스케줄링이 없던 시절에는 어땠을까요?
초창기 컴퓨터는 한 번에 하나의 프로그램만 실행할 수 있었습니다. 프로그램 A가 끝나야 프로그램 B를 실행할 수 있었죠.
이렇게 되면 CPU가 입출력을 기다리는 동안에도 다른 프로그램을 실행할 수 없어서 엄청난 낭비가 발생했습니다. 더 큰 문제는 사용자가 여러 작업을 동시에 할 수 없다는 것이었습니다.
바로 이런 문제를 해결하기 위해 멀티프로그래밍과 CPU 스케줄링이 등장했습니다. CPU 스케줄링을 사용하면 CPU 활용률을 극대화할 수 있습니다.
한 프로세스가 입출력을 기다리는 동안 다른 프로세스가 CPU를 사용할 수 있기 때문입니다. 또한 여러 사용자가 시스템을 공평하게 사용할 수 있게 됩니다.
무엇보다 시스템의 전체적인 성능과 응답성이 향상됩니다. 위의 코드를 살펴보겠습니다.
먼저 ready_queue는 실행을 기다리는 프로세스들이 대기하는 곳입니다. 새 프로세스가 도착하면 이 큐에 들어갑니다.
select_next_process 메서드가 바로 스케줄링의 핵심입니다. 이 메서드가 어떤 알고리즘을 사용하느냐에 따라 시스템의 성능이 크게 달라집니다.
실제 현업에서는 어떻게 활용될까요? 웹 서버를 운영한다고 가정해봅시다.
수많은 사용자의 요청이 동시에 들어옵니다. 운영체제의 스케줄러가 이 요청들을 효율적으로 처리해야 모든 사용자가 빠른 응답을 받을 수 있습니다.
스케줄링이 잘못되면 일부 사용자는 한참을 기다려야 할 수도 있습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "아, 그래서 여러 프로그램이 동시에 돌아가는 것처럼 보이는 거군요!" CPU 스케줄링을 이해하면 시스템의 동작 원리를 깊이 이해할 수 있고, 성능 문제를 진단할 때 큰 도움이 됩니다.
실전 팁
💡 - CPU 스케줄링은 운영체제의 핵심 기능이며, 시스템 성능에 직접적인 영향을 미칩니다
- 스케줄링 알고리즘에 따라 같은 작업도 처리 시간이 크게 달라질 수 있습니다
2. 선점형 vs 비선점형
김개발 씨가 운영체제 스터디에서 "선점형과 비선점형의 차이가 뭐예요?"라는 질문을 받았습니다. 분명히 책에서 봤는데 막상 설명하려니 헷갈립니다.
이 두 가지 방식의 차이를 제대로 이해해 봅시다.
선점형 스케줄링은 실행 중인 프로세스를 강제로 중단시킬 수 있는 방식입니다. 마치 응급 환자가 오면 진료 순서를 바꾸는 응급실과 같습니다.
반면 비선점형 스케줄링은 일단 CPU를 얻으면 스스로 놓을 때까지 계속 사용하는 방식입니다. 이는 이발소에서 이발이 끝날 때까지 기다리는 것과 비슷합니다.
다음 코드를 살펴봅시다.
# 비선점형 스케줄링 - 프로세스가 스스로 CPU를 반납
class NonPreemptiveScheduler:
def run_process(self, process):
# 프로세스가 완료될 때까지 실행
while not process.is_finished():
process.execute_one_cycle()
# 완료 후에야 다음 프로세스로 전환
# 선점형 스케줄링 - 타임 슬라이스마다 전환 가능
class PreemptiveScheduler:
def __init__(self, time_quantum=10):
self.time_quantum = time_quantum # 시간 할당량
def run_process(self, process):
# 정해진 시간만큼만 실행 후 강제 전환
for _ in range(self.time_quantum):
if process.is_finished():
break
process.execute_one_cycle()
김개발 씨는 스터디 모임에서 난감한 상황에 처했습니다. 선배가 "그래서 리눅스는 선점형이야, 비선점형이야?"라고 물었는데, 대답을 못 했기 때문입니다.
집에 돌아온 김개발 씨는 이 개념을 제대로 정리하기로 마음먹었습니다. 박시니어 씨에게 도움을 요청했습니다.
"선배, 선점형과 비선점형이 정확히 뭔지 설명해 주실 수 있나요?" 박시니어 씨는 웃으며 비유를 들었습니다. "비선점형은 이발소를 생각하면 돼요.
손님이 이발을 시작하면 끝날 때까지 다른 손님은 무조건 기다려야 해요. 아무리 급해도요." "그럼 선점형은요?" 김개발 씨가 물었습니다.
"선점형은 응급실이에요. 진료를 받던 환자가 있어도 더 위급한 환자가 오면 순서가 바뀔 수 있죠.
운영체제가 강제로 CPU를 빼앗을 수 있다는 거예요." 비선점형 스케줄링은 구현이 간단하다는 장점이 있습니다. 프로세스가 알아서 CPU를 반납하니까 복잡한 상태 관리가 필요 없습니다.
하지만 치명적인 단점이 있습니다. 하나의 프로세스가 CPU를 독점할 수 있다는 것입니다.
무한 루프에 빠진 프로그램이 있다면 다른 모든 프로그램이 멈춰버립니다. 선점형 스케줄링은 이런 문제를 해결합니다.
운영체제가 타이머 인터럽트를 사용해서 일정 시간이 지나면 강제로 프로세스를 중단시킵니다. 덕분에 모든 프로세스가 공평하게 CPU를 사용할 수 있습니다.
대신 구현이 복잡하고, 문맥 교환(context switch) 비용이 발생합니다. 위 코드를 보면 차이가 명확합니다.
비선점형은 **while not process.is_finished()**로 프로세스가 끝날 때까지 계속 실행합니다. 선점형은 time_quantum 만큼만 실행하고 멈춥니다.
현대의 대부분의 운영체제는 선점형을 사용합니다. Windows, Linux, macOS 모두 선점형입니다.
사용자가 여러 프로그램을 동시에 사용해야 하기 때문입니다. 하나의 프로그램이 다른 프로그램을 방해하면 안 됩니다.
하지만 비선점형이 아예 쓸모없는 것은 아닙니다. 단순한 임베디드 시스템이나 배치 처리 시스템에서는 비선점형이 더 효율적일 수 있습니다.
문맥 교환 비용이 없으니까요. 김개발 씨는 이제 자신 있게 대답할 수 있게 되었습니다.
"리눅스는 선점형이에요. 그래서 여러 프로그램이 동시에 잘 돌아가는 거죠!"
실전 팁
💡 - 현대 운영체제는 대부분 선점형 스케줄링을 사용합니다
- 선점형은 응답성이 좋고, 비선점형은 구현이 간단하고 오버헤드가 적습니다
3. 도착 시간과 버스트 시간
스케줄링 알고리즘을 공부하던 김개발 씨가 예제 문제를 풀다가 막혔습니다. "도착 시간 0, 버스트 시간 5"라고 적혀 있는데, 이게 정확히 무슨 의미인지 헷갈립니다.
이 두 가지 기본 개념을 확실히 짚고 넘어가 봅시다.
**도착 시간(Arrival Time)**은 프로세스가 준비 큐에 도착하는 시점입니다. 마치 음식점에 손님이 들어온 시간과 같습니다.
**버스트 시간(Burst Time)**은 프로세스가 CPU를 사용해야 하는 총 시간입니다. 손님이 음식을 먹는 데 걸리는 시간이라고 생각하면 됩니다.
이 두 값이 스케줄링 계산의 기초가 됩니다.
다음 코드를 살펴봅시다.
# 프로세스의 기본 정보를 담는 클래스
class Process:
def __init__(self, pid, arrival_time, burst_time):
self.pid = pid # 프로세스 ID
self.arrival_time = arrival_time # 도착 시간: 언제 준비 큐에 들어왔나
self.burst_time = burst_time # 버스트 시간: CPU가 얼마나 필요한가
self.remaining_time = burst_time # 남은 실행 시간
# 예시: 세 개의 프로세스 생성
processes = [
Process("P1", arrival_time=0, burst_time=5), # 시간 0에 도착, 5만큼 실행 필요
Process("P2", arrival_time=2, burst_time=3), # 시간 2에 도착, 3만큼 실행 필요
Process("P3", arrival_time=4, burst_time=1), # 시간 4에 도착, 1만큼 실행 필요
]
김개발 씨는 운영체제 시험을 앞두고 스케줄링 문제를 풀고 있었습니다. 문제에는 "P1: 도착 시간 0, 버스트 시간 5"라고 적혀 있었습니다.
숫자는 보이는데, 이걸 어떻게 해석해야 할지 막막했습니다. 박시니어 씨가 옆에서 설명을 시작했습니다.
"음식점을 생각해 봐요. 손님이 12시에 들어왔다면, 그게 도착 시간이에요.
그리고 그 손님이 식사하는 데 30분이 걸린다면, 그게 버스트 시간이고요." 도착 시간은 프로세스가 시스템에 제출되어 준비 큐에 들어간 시점입니다. 모든 프로세스가 동시에 도착하는 것은 아닙니다.
어떤 프로세스는 시간 0에, 어떤 프로세스는 시간 10에 도착할 수 있습니다. 스케줄러는 아직 도착하지 않은 프로세스는 선택할 수 없습니다.
버스트 시간은 프로세스가 다음 입출력 요청이나 종료까지 CPU를 연속으로 사용해야 하는 시간입니다. 정확히 말하면 CPU 버스트라고 합니다.
프로세스는 CPU 버스트와 I/O 버스트를 번갈아가며 실행됩니다. 왜 이 두 개념이 중요할까요?
스케줄링 알고리즘은 이 정보를 바탕으로 결정을 내립니다. 예를 들어 SJF(Shortest Job First) 알고리즘은 버스트 시간이 가장 짧은 프로세스를 먼저 실행합니다.
도착 시간을 무시하면 아직 도착하지도 않은 프로세스를 실행하려는 오류가 발생합니다. 위 코드에서 세 개의 프로세스를 만들었습니다.
P1은 시간 0에 도착해서 5단위 시간 동안 CPU가 필요합니다. P2는 시간 2에 도착하고 3단위가 필요합니다.
P3은 시간 4에 도착하고 1단위만 필요합니다. 시간 0에는 P1만 선택할 수 있습니다.
아직 P2와 P3은 도착하지 않았으니까요. 시간 2가 되면 P2가 도착하고, 시간 4가 되면 P3도 도착합니다.
스케줄러는 매 순간 "지금 선택 가능한 프로세스 중에서 누구를 실행할까"를 결정합니다. 실무에서는 버스트 시간을 정확히 알 수 없다는 문제가 있습니다.
프로세스가 얼마나 오래 실행될지 미리 알 수 없기 때문입니다. 그래서 과거 실행 기록을 바탕으로 예측하거나, 다른 방법을 사용합니다.
김개발 씨는 이제 문제를 자신 있게 풀 수 있게 되었습니다. "도착 시간 0, 버스트 시간 5라면, 이 프로세스는 시작부터 있었고 CPU를 5단위 시간 동안 사용하면 되는 거구나!"
실전 팁
💡 - 도착 시간이 다르면 같은 알고리즘도 다른 결과를 낼 수 있습니다
- 버스트 시간은 실제로는 예측값을 사용하는 경우가 많습니다
4. 대기 시간과 반환 시간
김개발 씨가 스케줄링 알고리즘의 성능을 비교하는 과제를 받았습니다. "평균 대기 시간과 평균 반환 시간을 계산하시오"라는 문제입니다.
이 두 가지 지표가 무엇이고 어떻게 계산하는지 알아봅시다.
**대기 시간(Waiting Time)**은 프로세스가 준비 큐에서 CPU를 기다린 총 시간입니다. 마치 병원에서 진료를 기다리는 시간과 같습니다.
**반환 시간(Turnaround Time)**은 프로세스가 도착해서 완료될 때까지 걸린 전체 시간입니다. 병원에 들어가서 진료를 마치고 나올 때까지의 총 시간이라고 생각하면 됩니다.
다음 코드를 살펴봅시다.
# 스케줄링 성능 지표 계산
def calculate_metrics(processes, completion_times):
results = []
for p in processes:
# 반환 시간 = 완료 시간 - 도착 시간
turnaround = completion_times[p.pid] - p.arrival_time
# 대기 시간 = 반환 시간 - 버스트 시간
waiting = turnaround - p.burst_time
results.append({
'pid': p.pid,
'turnaround_time': turnaround, # 총 소요 시간
'waiting_time': waiting # 순수 대기 시간
})
# 평균 계산
avg_turnaround = sum(r['turnaround_time'] for r in results) / len(results)
avg_waiting = sum(r['waiting_time'] for r in results) / len(results)
return results, avg_turnaround, avg_waiting
김개발 씨에게 과제가 주어졌습니다. 두 가지 스케줄링 알고리즘을 비교해서 어떤 것이 더 좋은지 판단하라는 것입니다.
하지만 "더 좋다"는 것을 어떻게 수치로 표현할 수 있을까요? 박시니어 씨가 힌트를 주었습니다.
"스케줄링 성능을 측정하는 대표적인 지표가 대기 시간과 반환 시간이에요. 이 두 가지로 알고리즘을 비교할 수 있어요." 대기 시간을 쉽게 이해하려면 놀이공원을 생각해 보세요.
롤러코스터를 타려고 줄을 섰습니다. 줄에서 기다린 시간이 바로 대기 시간입니다.
실제로 롤러코스터를 타는 시간(버스트 시간)은 포함되지 않습니다. 순수하게 기다리기만 한 시간입니다.
반환 시간은 더 포괄적입니다. 놀이공원 입구에 들어선 순간부터 롤러코스터를 타고 내릴 때까지의 모든 시간입니다.
줄 서서 기다린 시간(대기 시간)과 실제로 탑승한 시간(버스트 시간)을 모두 포함합니다. 수식으로 표현하면 이렇습니다.
- 반환 시간 = 완료 시간 - 도착 시간 - 대기 시간 = 반환 시간 - 버스트 시간 예를 들어 봅시다. 프로세스 P1이 시간 0에 도착하고, 버스트 시간이 5이며, 시간 10에 완료되었다면, 반환 시간은 10 - 0 = 10이고, 대기 시간은 10 - 5 = 5입니다.
왜 이 지표들이 중요할까요? 평균 대기 시간이 짧을수록 프로세스들이 빨리 CPU를 얻을 수 있다는 뜻입니다.
사용자 입장에서는 프로그램이 빨리 응답하는 것처럼 느껴집니다. 평균 반환 시간이 짧을수록 작업이 빨리 완료된다는 뜻입니다.
위 코드는 이 지표들을 계산하는 함수입니다. 각 프로세스의 완료 시간을 받아서 반환 시간과 대기 시간을 구합니다.
그리고 전체 프로세스의 평균값도 계산합니다. 스케줄링 알고리즘을 비교할 때는 보통 평균값을 사용합니다.
같은 프로세스 집합에 대해 알고리즘 A의 평균 대기 시간이 5이고 알고리즘 B가 8이라면, 일반적으로 A가 더 좋다고 판단합니다. 김개발 씨는 이제 과제를 해결할 수 있게 되었습니다.
각 알고리즘으로 스케줄링을 시뮬레이션하고, 평균 대기 시간과 평균 반환 시간을 비교하면 됩니다.
실전 팁
💡 - 대기 시간과 반환 시간은 스케줄링 알고리즘 비교의 핵심 지표입니다
- 반환 시간 = 대기 시간 + 버스트 시간 이라는 관계를 기억하세요
5. 응답 시간과 처리량
김개발 씨가 웹 서버 성능 테스트 결과를 보고 있었습니다. "응답 시간 200ms, 처리량 1000 req/sec"라고 적혀 있습니다.
스케줄링 성능을 측정하는 또 다른 중요한 지표인 응답 시간과 처리량에 대해 알아봅시다.
**응답 시간(Response Time)**은 요청을 제출한 후 첫 번째 응답이 시작될 때까지 걸린 시간입니다. 마치 식당에서 주문 후 첫 음식이 나올 때까지 기다리는 시간과 같습니다.
**처리량(Throughput)**은 단위 시간당 완료된 프로세스의 수입니다. 식당이 한 시간에 몇 팀의 손님을 받을 수 있는지와 비슷합니다.
다음 코드를 살펴봅시다.
# 응답 시간과 처리량 계산
class SchedulerMetrics:
def __init__(self):
self.first_response_times = {} # 각 프로세스의 첫 응답 시간
self.completion_times = {} # 각 프로세스의 완료 시간
def record_first_response(self, pid, current_time, arrival_time):
# 응답 시간 = 첫 CPU 할당 시간 - 도착 시간
if pid not in self.first_response_times:
self.first_response_times[pid] = current_time - arrival_time
def calculate_throughput(self, total_time):
# 처리량 = 완료된 프로세스 수 / 총 시간
completed_count = len(self.completion_times)
return completed_count / total_time if total_time > 0 else 0
def get_avg_response_time(self):
times = self.first_response_times.values()
return sum(times) / len(times) if times else 0
김개발 씨는 회사에서 운영하는 웹 서비스의 성능 보고서를 검토하고 있었습니다. 보고서에는 "평균 응답 시간"과 "초당 처리량"이라는 수치가 있었습니다.
이 숫자들이 스케줄링과 어떤 관련이 있는 걸까요? 박시니어 씨가 설명을 시작했습니다.
"앞서 배운 대기 시간과 반환 시간 외에도 응답 시간과 처리량이라는 중요한 지표가 있어요." 응답 시간은 대기 시간과 비슷하지만 다릅니다. 대기 시간은 CPU를 기다린 총 시간입니다.
하지만 응답 시간은 프로세스가 제출된 후 처음으로 CPU를 얻을 때까지의 시간입니다. 차이를 예로 들어볼까요?
라운드 로빈 스케줄링에서 프로세스가 CPU를 얻었다가 뺏기고, 다시 기다렸다가 또 얻는 과정을 반복합니다. 대기 시간은 이 모든 기다림의 합입니다.
하지만 응답 시간은 맨 처음 CPU를 얻는 순간까지만 측정합니다. 왜 응답 시간이 중요할까요?
대화형 시스템에서는 사용자가 버튼을 클릭했을 때 빠르게 반응하는 것이 중요합니다. 완료까지 10초가 걸려도, 0.1초 만에 "처리 중입니다"라는 메시지가 뜨면 사용자는 시스템이 동작하고 있다고 느낍니다.
처리량은 시스템의 전체적인 효율성을 나타냅니다. 1시간 동안 100개의 작업을 처리하면 처리량은 100작업/시간입니다.
처리량이 높을수록 시스템이 효율적으로 일하고 있다는 뜻입니다. 응답 시간과 처리량은 때로 상충됩니다.
응답 시간을 줄이려면 자주 문맥 교환을 해야 합니다. 그런데 문맥 교환에는 비용이 들기 때문에 처리량이 떨어질 수 있습니다.
반대로 처리량을 높이려면 문맥 교환을 줄여야 하는데, 그러면 응답 시간이 길어집니다. 위 코드에서 record_first_response 메서드는 프로세스가 처음 CPU를 얻는 순간을 기록합니다.
같은 프로세스가 다시 CPU를 얻어도 무시합니다. 오직 첫 번째만 중요하기 때문입니다.
시스템의 목적에 따라 중요한 지표가 달라집니다. 웹 서버처럼 사용자와 상호작용하는 시스템은 응답 시간이 중요합니다.
배치 처리 시스템처럼 대량의 작업을 처리하는 시스템은 처리량이 더 중요합니다. 김개발 씨는 이제 성능 보고서를 더 잘 이해할 수 있게 되었습니다.
"응답 시간 200ms는 사용자가 클릭하고 200ms 만에 첫 반응이 온다는 거고, 처리량 1000 req/sec는 초당 1000개 요청을 처리한다는 거구나!"
실전 팁
💡 - 대화형 시스템은 응답 시간을, 배치 시스템은 처리량을 더 중시합니다
- 두 지표는 trade-off 관계에 있어서 동시에 최적화하기 어렵습니다
6. 스케줄링 기준
김개발 씨가 "최적의 스케줄링 알고리즘은 뭐예요?"라고 물었습니다. 박시니어 씨는 "그건 무엇을 최적화하느냐에 따라 달라요"라고 대답했습니다.
스케줄링 알고리즘을 평가하는 다양한 기준에 대해 알아봅시다.
**스케줄링 기준(Scheduling Criteria)**은 스케줄링 알고리즘의 성능을 평가하는 척도입니다. 마치 자동차를 평가할 때 연비, 속도, 안전성 등 여러 기준이 있는 것과 같습니다.
CPU 활용률, 처리량, 반환 시간, 대기 시간, 응답 시간 등이 대표적인 기준입니다. 어떤 기준을 중시하느냐에 따라 최적의 알고리즘이 달라집니다.
다음 코드를 살펴봅시다.
# 스케줄링 알고리즘 평가 기준
class SchedulingCriteria:
def __init__(self, processes, total_time, idle_time):
self.processes = processes
self.total_time = total_time
self.idle_time = idle_time
def cpu_utilization(self):
# CPU 활용률 = (전체 시간 - 유휴 시간) / 전체 시간 * 100
busy_time = self.total_time - self.idle_time
return (busy_time / self.total_time) * 100
def evaluate_all(self, metrics):
return {
'cpu_utilization': self.cpu_utilization(), # 높을수록 좋음
'throughput': metrics.throughput, # 높을수록 좋음
'avg_turnaround': metrics.avg_turnaround, # 낮을수록 좋음
'avg_waiting': metrics.avg_waiting, # 낮을수록 좋음
'avg_response': metrics.avg_response # 낮을수록 좋음
}
김개발 씨는 운영체제 책에서 다양한 스케줄링 알고리즘을 공부했습니다. FCFS, SJF, 라운드 로빈, 우선순위 스케줄링 등 종류가 많았습니다.
그런데 문득 궁금해졌습니다. "이 중에서 가장 좋은 알고리즘은 뭘까?" 박시니어 씨가 고개를 저었습니다.
"가장 좋은 알고리즘이라는 건 없어요. 무엇을 기준으로 하느냐에 따라 답이 달라지거든요." 스케줄링 기준은 크게 다섯 가지로 나눌 수 있습니다.
첫째, **CPU 활용률(CPU Utilization)**입니다. CPU가 얼마나 바쁘게 일하는지를 나타냅니다.
100%에 가까울수록 CPU가 놀지 않고 열심히 일한다는 뜻입니다. 비싼 CPU를 효율적으로 사용하고 싶다면 이 지표를 높여야 합니다.
둘째, **처리량(Throughput)**입니다. 단위 시간당 완료된 프로세스 수입니다.
배치 처리 시스템처럼 많은 작업을 처리해야 하는 경우 중요합니다. 셋째, **반환 시간(Turnaround Time)**입니다.
프로세스가 제출되어 완료될 때까지의 총 시간입니다. 작업이 빨리 끝나기를 원한다면 이 지표를 줄여야 합니다.
넷째, **대기 시간(Waiting Time)**입니다. 프로세스가 준비 큐에서 기다린 총 시간입니다.
대기 시간이 길면 프로세스가 CPU를 얻기까지 오래 걸린다는 뜻입니다. 다섯째, **응답 시간(Response Time)**입니다.
요청 후 첫 응답까지의 시간입니다. 대화형 시스템에서 가장 중요한 지표입니다.
이 기준들 중 어떤 것을 최대화하고 어떤 것을 최소화해야 할까요? 일반적으로 CPU 활용률과 처리량은 높을수록 좋습니다.
반면 반환 시간, 대기 시간, 응답 시간은 낮을수록 좋습니다. 문제는 이 기준들이 서로 충돌한다는 것입니다.
응답 시간을 줄이려면 자주 문맥 교환을 해야 하는데, 그러면 오버헤드가 증가해서 처리량이 떨어집니다. 처리량을 높이려면 문맥 교환을 줄여야 하는데, 그러면 응답 시간이 길어집니다.
그래서 시스템의 목적에 따라 적절한 알고리즘을 선택해야 합니다. 웹 서버는 응답 시간이 중요하니까 라운드 로빈 같은 알고리즘이 적합합니다.
과학 계산용 서버는 처리량이 중요하니까 FCFS나 SJF가 나을 수 있습니다. 김개발 씨는 이제 이해했습니다.
"결국 trade-off의 문제군요. 상황에 맞게 선택해야 하는 거네요!" 박시니어 씨가 고개를 끄덕였습니다.
"맞아요. 완벽한 알고리즘은 없어요.
하지만 상황에 맞는 최선의 알고리즘은 있죠."
실전 팁
💡 - 스케줄링 기준은 상충 관계에 있으므로 모든 기준을 동시에 최적화할 수 없습니다
- 시스템의 목적(대화형, 배치, 실시간 등)에 따라 중요한 기준이 달라집니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
교착 상태 (Deadlock) 완벽 가이드
운영체제에서 발생하는 교착 상태의 개념부터 예방, 회피, 탐지까지 완벽하게 이해할 수 있는 가이드입니다. 실무에서 마주칠 수 있는 동시성 문제를 해결하는 핵심 지식을 담았습니다.
동기화 도구 완벽 가이드
멀티스레드 프로그래밍에서 핵심이 되는 동기화 도구들을 알아봅니다. 뮤텍스, 세마포어, 모니터 등 운영체제의 동기화 메커니즘을 실무 예제와 함께 쉽게 이해할 수 있습니다.
프로세스 동기화 완벽 가이드
멀티스레드 환경에서 여러 프로세스가 공유 자원에 안전하게 접근하는 방법을 알아봅니다. Race Condition부터 Peterson 알고리즘까지 동기화의 핵심 개념을 실무 예제와 함께 쉽게 설명합니다.
CPU 스케줄링 알고리즘 (2)
Round Robin부터 MLFQ까지, 현대 운영체제가 사용하는 핵심 CPU 스케줄링 알고리즘들을 실무 예제와 함께 알아봅니다. 초급 개발자도 쉽게 이해할 수 있도록 스토리텔링 방식으로 설명합니다.
CPU 스케줄링 알고리즘 완벽 가이드 (1)
운영체제의 핵심인 CPU 스케줄링 알고리즘을 초급 개발자도 쉽게 이해할 수 있도록 설명합니다. FCFS부터 HRRN까지, 각 알고리즘의 동작 원리와 장단점을 실무 스토리와 함께 배워봅니다.