윈도우즈 시스템 프로그래밍

윈도우즈 시스템 프로그래밍 9장 - 스케줄링 알고리즘과 우선순위

111-000-111 2021. 7. 31. 16:35

 

 

 

윈도우즈 시스템 프로그래밍이라는 책과 해당 책의 저자이신 윤성우님의 강의를 통해 공부한 내용을 정리하는 글입니다.

 

 

 

 


 

 

 

범용 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;
}