윈도우즈 시스템 프로그래밍 9장 - 스케줄링 알고리즘과 우선순위
윈도우즈 시스템 프로그래밍이라는 책과 해당 책의 저자이신 윤성우님의 강의를 통해 공부한 내용을 정리하는 글입니다.
범용 OS와 리얼타임(Real Time) OS의 차이점
⦁ RTOS(Real Time Operating System)는 응답성이 일반 OS보다 좋다.
⦁ 일반 OS는 범용적인 사용을 위해서 디자인 되어 있다.
⦁ RTOS는 사용 영역이 제한적이다보니, 단순하게 디자인되어 있고 일반 OS에 비해서 훨씬 가볍기 떄문에 응답성이 좋은것이지 속도가 빠른 것이 아니다.
Soft RTOS vs Hard RTOS
⦁ 위에서 소개한 RTOS에 대한 설명은 Soft RTOS에 해당한다.
⦁ Hard RTOS는 데드라인(Dead Line)을 중시한다.
⦁ 데드라인은 시간에 크리티컬한 상황에서 발생한다. 예를들어 자동차 ABS 시스템이 있다.
선점형(Preemptive) OS와 비선점형(Non-Preemptive) OS
⦁ 비선점형 OS
현재 실행 중인 프로세스보다 높은 우선순위의 프로세스가 등장한다고 해서 실행의 대상을 바로 변경하지 않는다.
보다 높은 우선순위의 프로세스가 실행되기 위해서는 프로세스가 명시적으로 CPU를 양보할 때까지, 혹은 I/O 작업 등으로 블로킹 상태에 놓일 떄까지 기다려야 한다.
⦁ 선점형 OS
현재 실행 중인 프로세스보다 높은 우선순위의 프로세스가 등장하면 스케줄러에 의한 실행순서 조정이 적극 이루어진다.
라운드 로빈(Round-Robin) 스케줄링 알고리즘
⦁ 우선순위가 같은 프로세스의 경우에는 형평성 유지를 위해 정해진 시간 간격(타임 슬라이스)만큼만 실행하고 다른 프로세스에게 CPU 할당을 넘기는 방식의 라운드 로빈 알고리즘을 적용한다.
⦁ 타임 슬라이스가 길어지면 인터렉티브한 시스템에서 문제가 될 수 있고, 너무 짧으면 컨텍스트 스위칭이 빈번해져 성능이 저하된다.
스케줄러가 동작하는 상황
⦁ 매 타임 슬라이스마다 스케줄러 동작
⦁ 프로세스가 생성 및 소멸될 떄마다 스케줄러 동작
⦁ 현재 실행 중인 프로세스가 블로킹 상태에 놓일 떄마다 스케줄러 동작
Priority Inversion
프로세스 A > 프로세스 B > 프로세스 C 와 같은 우선순위를 갖는 프로세스가 있다고 가정하자.
A가 실행되던 중 프로세스 C가 계산해서 줘야 하는 값이 아직 도착하지 않아서 작업을 멈췄다. 그래서 A는 C가 작업할 수 있게끔 Blocked 상태가 되었지만 B가 C에 비해 우선순위가 높으므로 작업을 하게된다.
위와 같은 상황에서는 프로세스 A가 C에게 우선순위를 위임하면 된다. 운영체제별로 Priority Inversion의 해결법은 다양하다.
Windows 프로세스 우선순위
Priority | Meaning |
IDLE_PRIORITY_CLASS | 기준 우선순위 4 |
NORMAL_PRIORITY_CLASS | 기준 우선순위 9 |
HIGH_PRIORITY_CLASS | 기준 우선순위 13 |
REALTIME_PRIORITY_CLASS | 기준 우선순위 24 |
ABOVE_NORMAL_PRIORITY_CLASS | NORMAL_PRIORITY_CLASS 보다 높고 HIGH_PRIORITY_CLASS보다 낮은 우선순위. 단, Windows NT and Me 이하(포함해서)에서는 지원되지 않는다. |
BELOW_NORMAL_PRIORITY_CLASS | IDLE_PRIORITY_CLASS보다 높고 NORMAL_PRIORITY_CLASS보다 낮은 우선순위. 단, Windows NT and Me(포함해서)에서는 지원되지 않는다. |
⦁ ABOVE_NORMAL_PRIORITY_CLASS.cpp
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR* argv[])
{
STARTUPINFO siNORMAL = { 0, };
PROCESS_INFORMATION piNORMAL;
TCHAR commandOne[] = _T("NORMAL_PRIORITY_CLASS.exe");
STARTUPINFO siBELOW = { 0, };
PROCESS_INFORMATION piBELOW;
TCHAR commandTwo[] = _T("BELOW_NORMAL_PRIORITY_CLASS.exe");
siNORMAL.cb = sizeof(siNORMAL);
siBELOW.cb = sizeof(siBELOW);
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
CreateProcess(NULL, commandOne, NULL, NULL, TRUE, 0, NULL, NULL, &siNORMAL, &piNORMAL);
CreateProcess(NULL, commandTwo, NULL, NULL, TRUE, 0, NULL, NULL, &siBELOW, &piBELOW);
while (1)
{
for (DWORD i = 0; i < 10000; i++)
for (DWORD i = 0; i < 10000; i++);
//Sleep(10);
_fputts(_T("ABOVE_NORMAL_PRIORITY_CLASS Process \n"),stdout);
}
return 0;
}
⦁ NORMAL_PRIORITY_CLASS.cpp
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR* argv[])
{
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
while (1)
{
for (DWORD i = 0; i < 10000; i++)
for (DWORD i = 0; i < 10000; i++);
//Sleep(10);
_fputts(_T("NORMAL_PRIORITY_CLASS Process \n"), stdout);
}
return 0;
}
⦁ BELOW_NORMAL_PRIORITY_CLASS.cpp
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCHAR* argv[])
{
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
while (1)
{
for (DWORD i = 0; i < 10000; i++)
for (DWORD i = 0; i < 10000; i++);
//Sleep(10);
_fputts(_T("BELOW_NORMAL_PRIORITY_CLASS Process \n"), stdout);
}
return 0;
}