라운드-로빈 방식을 사용해서 프로세스 처리는 SJF(Shortest Job First) 기법으로 했습니다.
만든이 : 미쉘린




// c++ header
#include 

// STL header
#include 
#include 

// c header
#include 

// using std
using namespace std;

// define const integer
#define _BURST_TIME_RANGE_		40			// Burst Time 범위				= 1~40 변경가능
#define _ARRIVAL_INTERVAL_		2			// 프로세스 Arrival 시간간격	= 2,   변경가능
#define _NUMBER_OF_PROCESS_		10			// 프로세스의 개수			= 10,  변경가능 (ex:1000)
	
#define _RESULT_FILE_			"_RESULT.txt"

// _PDATA = 프로세스 구조체
typedef struct _pdata
{
	bool completed;						// 프로세스가 종료되었는가?
	int process_ID;						// 프로세스 ID
	int arrival_time;					// Arrivial Time
	int iburst_time;					// Initial Burst Time
	int burst_time;						// Burst Time
	int turn_around_time;				// Turn-Around Time
	int waiting_time;					// Waiting Time
	int response_time;					// Response Time
} _PDATA;

// vector<_PDATA> 에서 generic max_element 를 사용하기위한 compare 사용자 함수
bool v_comp(const _PDATA &a, const _PDATA &b)
{	return a.burst_time < b.burst_time;		}

// vector<_PDATA> 에서 generic sort 를 사용하기위한 compare 사용자 함수
bool v_sort(const _PDATA &a, const _PDATA &b)
{	return a.process_ID < b.process_ID;		}

// 결과로 출력할 파일명 리턴
// return		: 파일명				= NULL 이면 오류발생했다는 의미
// argument #1	: destroy				= true 이면 메모리 해제
char* _result_file_(bool destroy);

// 파일 포인터 리턴
// return		: 파일 포인터			= NULL 이면 오류발생했다는 의미
// argument #1	: destroy				= true 이면 메모리 해제
FILE* _result_file_access_(bool destroy);

// PDATA 구조체를 생성하는 함수
// return		: 생성된 PDATA 구조체 포인터
// argument #1	: pid					= 프로세스 ID
// argument #2	: atime					= Arrival Time
// argument #3	: btime					= Burst Time
_PDATA* construct_PDATA(int pid, int atime, int btime);

// 결과물 파일 생성을 위한 타임스탬프 생성
char* now_time_to_string();

// vector<_PDATA> 초기화 작업
void initilize(vector<_PDATA> &v);

// 첫번째 작업
void first_process_work(vector<_PDATA> &v);

// 루프 작업
// while(true) 루프에 넣고 계속 돌리면,
// 모든 프로세스가 completed 처리됨
bool loop_process_work(vector<_PDATA> &v);

// 결과물 출력 - 모니터 출력
void show_result_MONITOR(vector<_PDATA> &v);

// 결과물 출력 - 파일 출력
void show_result_FILE(vector<_PDATA> &v);

// 프로그램 종료 작업
void finalize(vector<_PDATA> &v);

// 프로세스를 ID 순으로 오름차순 정렬함
void sort_by_processID_ascend(vector<_PDATA> &v);

void main()
{
	vector<_PDATA> v;
	
	initilize(v);
	first_process_work(v);
	while( true ) if( loop_process_work(v) ) break;
	sort_by_processID_ascend(v);
	show_result_MONITOR(v);	
	show_result_FILE(v);	
	finalize(v);	
}

char* _result_file_(bool destroy)
{
	static bool initialized;
	static char* result_file;

	if( destroy )
	{
		free(result_file);	// free
		initialized = false;
		return NULL;
	}

	if( !initialized )
	{
		initialized = true;
		result_file = now_time_to_string();	// malloc
	}
	return result_file;
}

FILE* _result_file_access_(bool destroy)
{
	static bool initialized;
	static FILE* fp;
	static errno_t err;

	if( destroy )
	{
		err != 0 ? NULL : fclose(fp);
		initialized = false;
		return NULL;
	}

	if( !initialized )
	{
		initialized = true;
		err = fopen_s(&fp, _result_file_(0), "w");
		if( err != 0 )
			printf( "- 파일을 생성하는 도중에 오류가 발생했습니다.\n" );
	}

	return (err != 0 ? NULL : fp);
}

_PDATA* construct_PDATA(int pid, int atime, int btime)
{
	_PDATA *d = (_PDATA*)malloc(sizeof(_PDATA));

	d->completed = false;
	d->process_ID = pid;
	d->arrival_time = atime;
	d->iburst_time = btime;
	d->burst_time = btime;
	d->turn_around_time = 0;
	d->waiting_time = 0;
	d->response_time = 0;

	return d;
}

char* now_time_to_string()
{	
	struct tm newtime;
	char am_pm[] = "AM";
	__time64_t long_time;

	_time64( &long_time );					// Get time as 64-bit integer.
	// Convert to local time.
	_localtime64_s( &newtime, &long_time );	// C4996
	// Note: _localtime64 deprecated; consider _localetime64_s

	if( newtime.tm_hour > 12 )				// Set up extension.
		strcpy_s( am_pm, sizeof(am_pm), "PM" );
	if( newtime.tm_hour > 12 )				// Convert from 24-hour
		newtime.tm_hour -= 12;				//   to 12-hour clock.
	if( newtime.tm_hour == 0 )				// Set hour to 12 if midnight.
		newtime.tm_hour = 12;

	char *buff = (char*)malloc(sizeof(char)*30);
	memset(buff, NULL, sizeof(char)*30);
	asctime_s( buff, sizeof(char)*30, &newtime );
	strftime( buff, sizeof(char)*30, "%y%m%d_%H%M%S", &newtime );
	strcat_s( buff, sizeof(char)*30, _RESULT_FILE_ );

	return buff;
}

void initilize(vector<_PDATA> &v)
{
	vector<_PDATA>::iterator v_it = v.begin();
	int i = 0;
	int arrivalInterval = 0;
	srand( (unsigned)time( NULL ) );
	FILE *fp = _result_file_access_(0);

	// 프로세스 생성과 출력
	char *msg = "- 프로세스 생성과 출력\n";
	printf(msg);
	fprintf(fp, msg);
	while( i++ < _NUMBER_OF_PROCESS_ )
	{	
		_PDATA *d = 
			construct_PDATA(i, arrivalInterval, rand()%_BURST_TIME_RANGE_+1); // malloc
		v.push_back(*d);
		free(d); // free
		arrivalInterval += _ARRIVAL_INTERVAL_;
	}

	for( v_it=v.begin(); v_it!=v.end(); v_it++ )	
	{
		printf("P[%d]=%d\n", v_it->process_ID, v_it->iburst_time);	
		fprintf(fp, "P[%d]=%d\n", v_it->process_ID, v_it->burst_time);
	}
}

void first_process_work(vector<_PDATA> &v)
{
	vector<_PDATA>::iterator v_it = v.begin();
	int timeQuantum = 0;
	int responseInterval = 0;
	int waitingTime = 0;
	FILE *fp = _result_file_access_(0);

	// timeQuantum = 프로세스의 첫번째 값 / 2 (반올림)
	timeQuantum = (int)( (float)v_it->burst_time/2.0+0.5 );	

	// 모든 프로세스에 대해 timeQuantum 를 빼준다
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		v_it->burst_time -= timeQuantum;	
		v_it->response_time = responseInterval;
		v_it->waiting_time = waitingTime;
		responseInterval += timeQuantum;	

		v_it->burst_time >= 0 ?
			waitingTime += timeQuantum :		
			waitingTime += v_it->burst_time + timeQuantum;

		if( !v_it->completed && v_it->burst_time <= 0 )
		{
			v_it->burst_time = 0;
			v_it->turn_around_time = v_it->iburst_time + v_it->waiting_time;
			v_it->completed = true;
		}
	}

	sort(v.begin(), v.end(), v_comp);
	// 프로세스를 크기가 작은 순서대로 출력
	char *msg = "- FIRST, 프로세스 처리후, 프로세스를 크기가 작은 순서대로 출력\n";
	printf(msg);
	fp != NULL ? fprintf(fp, msg) : NULL;
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		printf("P[%d]=%d\n", v_it->process_ID, v_it->burst_time);
		fp != NULL ? fprintf(fp, "P[%d]=%d\n", v_it->process_ID, v_it->burst_time) : NULL;
	}
}

bool loop_process_work(vector<_PDATA> &v)
{	
	vector<_PDATA>::iterator v_it = v.begin();
	int timeQuantum = 0;
	int processWorkingCount = 0;
	int waitingTime = 0;
	FILE *fp = _result_file_access_(0);

	// timeQuantum = (프로세스 에서 가장 큰 수) / 2
	v_it = max_element( v.begin(), v.end(), v_comp );
	if( v_it->completed ) return true;
	timeQuantum = (int)( (float)v_it->burst_time/2.0+0.5 );

	// 모든 프로세스에 대해 timeQuantum 를 빼준다
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		if( !v_it->completed )
		{
			v_it->burst_time -= timeQuantum;
			processWorkingCount++;

			v_it->burst_time >= 0 ?
				waitingTime += timeQuantum :		
				waitingTime += v_it->burst_time + timeQuantum;

			if( v_it->burst_time <= 0 )
			{
				v_it->burst_time = 0;
				v_it->turn_around_time = v_it->iburst_time + v_it->waiting_time;						
			}
		}
	}

	// 프로세스를 크기가 작은 순서대로 출력
	char *msg = "- LOOP, 프로세스 처리후, 프로세스를 크기가 작은 순서대로 출력\n";
	printf(msg);
	fp != NULL ? fprintf(fp, msg) : NULL;
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{	
		if( v_it->completed ) 
			continue;
		else if( v_it->burst_time == 0 )
			v_it->completed = true;

		printf("P[%d]=%d\n", v_it->process_ID, v_it->burst_time);
		fp != NULL ? fprintf(fp, "P[%d]=%d\n", v_it->process_ID, v_it->burst_time) : NULL;
	}

	return processWorkingCount == 0;	
}

void show_result_MONITOR(vector<_PDATA> &v)
{
	vector<_PDATA>::iterator v_it = v.begin();

	// process ID, burst time 출력
	printf("%15s", "process ID");
	printf("%15s\n", "burst time");
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		printf("%15d", v_it->process_ID);
		printf("%15d\n", v_it->iburst_time);		
	}

	// process ID, turn-around time, waiting time, response time 출력
	printf("%15s", "process ID");
	printf("%18s", "turn-around time");
	printf("%15s", "waiting time");
	printf("%15s\n", "response time");
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		printf("%15d", v_it->process_ID);
		printf("%18d", v_it->turn_around_time);
		printf("%15d", v_it->waiting_time);
		printf("%15d\n", v_it->response_time);
	}
}

void show_result_FILE(vector<_PDATA> &v)
{
	vector<_PDATA>::iterator v_it = v.begin();
	FILE *fp = _result_file_access_(0);
	if( fp == NULL ) return;

	// process ID, burst time 출력
	fprintf(fp, "%15s", "process ID");
	fprintf(fp, "%15s\n", "burst time");
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		fprintf(fp, "%15d", v_it->process_ID);
		fprintf(fp, "%15d\n", v_it->iburst_time);		
	}

	// process ID, turn-around time, waiting time, response time 출력
	fprintf(fp, "%15s", "process ID");
	fprintf(fp, "%18s", "turn-around time");
	fprintf(fp, "%15s", "waiting time");
	fprintf(fp, "%15s\n", "response time");
	for( v_it=v.begin(); v_it!=v.end(); v_it++ )
	{
		fprintf(fp, "%15d", v_it->process_ID);
		fprintf(fp, "%18d", v_it->turn_around_time);
		fprintf(fp, "%15d", v_it->waiting_time);
		fprintf(fp, "%15d\n", v_it->response_time);
	}
}

void finalize(vector<_PDATA> &v)
{
	if( _result_file_access_(0) != NULL )
		printf("- 결과 파일 생성, %s\n", _result_file_(0));
	_result_file_(1);
	_result_file_access_(1);
	v.clear();
}

void sort_by_processID_ascend(vector<_PDATA> &v)
{
	sort(v.begin(), v.end(), v_sort);
}
WIN32API/MFC 카테고리에서 포스팅중인
[윈도우 시스템 프로그래밍]의 참고자료로 사용할 포스팅입니다 --;;

코드가 좀 뷁스럽구요. 라운드-로빈, SJF 참고로만 사용하면 될 듯 합니다.

#define _BURST_TIME_RANGE_  40   // Burst Time 범위    = 1~40 변경가능
#define _ARRIVAL_INTERVAL_  2    // 프로세스 Arrival 시간간격 = 2,   변경가능
#define _NUMBER_OF_PROCESS_  10  // 프로세스의 개수   = 10,  변경가능 (ex:1000)

이 부분은 입맛대로 수정하면 됩니다 ㄷㄷ
소스가 넘 길어서 코드도 걍 첨부합니다.


사용자 삽입 이미지

Comment List

  1. BlogIcon ㅎㅎㅎ 애기오리
    2008.12.01 11:23 신고
    메일로 질문하시는 분들이 많으신데 컴파일은 비주얼 스튜디오 2005 C++ 로 하시면 됩니다.
    VS 6.0 에서 하실 분들은 _s 붙은 쓰레드관련 안전함수를 수정하시면 됩니다.
    _s 붙은거 다 떼면 될듯 ㅎㅎ..

Leave a Comment