進程調度算法C語言實現

進程調度算法C語言實現

#define _CRT_SECURE_NO_WARNINGS
#define NUMBER 5

#include <stdio.h>
#include <windows.h>
char process_name[NUMBER] = { 'A', 'B', 'C', 'D', 'E' };
int arrive_time[NUMBER] = { 0, 2, 2, 3, 4 };
int server_time[NUMBER] = { 1, 3, 5, 2, 4 };
int fcfs_finished[NUMBER];
int fcfs_work[NUMBER];
double a_fcks_work[NUMBER];
typedef struct name_server{
	char process_name;
	int arrive_time;
	int server_time;
	int finished;
	int work;
	double a_work;
	double prioprity;
	int is_finished;//代表輪轉週期結束時,當前進程是否結束
};


void init_data(name_server *init_data);
void chang_position(name_server *temp_name_server, int index, int temp_value);
void calc_work_or_a_work(name_server *new_name_server_psa);
void print(name_server print_struct[5]);
void recovery_order(name_server *new_name_server, name_server *old_name_server);
void fcfs();
void sjf();
void psa();


//先來先服務
void fcfs() {
	name_server name_server_fcfs[NUMBER];
	//初始化
	init_data(name_server_fcfs);
	int is_true = 1;
	int temp_sum = 0;
	int is_wait = 0;
	while (is_true){
		//完成時間
		int is_finished = 0;
		for (int i = 0; i<NUMBER; i++) {
			//當時間無法達到到達時刻時執行
			if (is_wait > NUMBER+1) {
				temp_sum++;
				is_wait = 0;
				break;
			}

			//判斷是否到達
			if (name_server_fcfs[i].arrive_time > temp_sum) {
				is_wait++;
				continue;
			}

			if (name_server_fcfs[i].is_finished == 1){
				is_finished++;
				is_wait++;
				if (is_finished == NUMBER){
					is_true = 0;
					break;
				}
				continue;
			}
		

			//完成時間
			name_server_fcfs[i].finished = temp_sum + name_server_fcfs[i].server_time;
			temp_sum += name_server_fcfs[i].server_time;
			name_server_fcfs[i].is_finished = 1;
			is_wait = 0;
			break;
		}
	}

	calc_work_or_a_work(name_server_fcfs);
}

//短作業優先
void sjf() {
	//初始化一個進程名與服務時間有關的結構體
	name_server name_server_sjf[NUMBER];
	//初始化數據
	init_data(name_server_sjf);

	//完成時間的計算
	int temp_sum = 0;
	double avg_work = 0.0;
	double avg_a_work = 0.0;
	for (int j = 0; j < NUMBER; j++) {//循環進程的次數
			if (j == 0) {//0時刻進入的進程先執行
				name_server_sjf[j].finished = temp_sum + name_server_sjf[j].server_time;
			}
			else{
				//循環遍歷查找是否滿足到達時間
				int temp = 0;
				for (int i = j;i<NUMBER-j;i++){
					if (name_server_sjf[i].arrive_time > temp_sum){
						temp++;
					}
				}
				//不滿足到達條件進入下次循環,等待進程到達
				if(temp == NUMBER - j - 1){
					if (j < NUMBER - 1){
						j--;
						temp_sum++;
						continue;
					}
				}

				int min_index = j;
				//查找剩餘進程中最小的服務時間的進程
				for (int i = j + 1; i<NUMBER; i++) {
					name_server min = name_server_sjf[min_index];


					//判斷是否到達
					if (name_server_sjf[i].arrive_time > temp_sum){
						//進入每次對比的最後一次,進行向前替換
						if (i == NUMBER-1) {
							//交換位置
							chang_position(name_server_sjf, min_index, j);
						}
						continue;
					}

					if (min.server_time > name_server_sjf[i].server_time) {
						min_index = i;
					}

					if (i == NUMBER-1) {
						//交換位置
						chang_position(name_server_sjf, min_index, j);
					}
				
				}
				name_server_sjf[j].finished = temp_sum + name_server_sjf[j].server_time;
			}
			temp_sum += name_server_sjf[j].server_time;
	}
	
	//恢復進程名的順序
	name_server new_name_server_sjf[NUMBER];
	recovery_order(new_name_server_sjf, name_server_sjf);

	//輸出計算後的數據
	calc_work_or_a_work(new_name_server_sjf);
}	

//優先級
void psa() {
	//初始化一個進程名與服務時間有關的結構體
	name_server name_server_psa[NUMBER];
	//初始化數據
	init_data(name_server_psa);

	//總完成時間
	int temp_sum = 0;
	for (int i = 0; i<NUMBER; i++) {
		if (i == 0) {
			name_server_psa[i].finished = arrive_time[i] + server_time[i];
			temp_sum += name_server_psa[i].finished;
		}
		else {

			//循環遍歷查找是否滿足到達時間
			int temp = 0;
			for (int j = i; j<NUMBER - i; j++){
				if (name_server_psa[j].arrive_time > temp_sum){
					temp++;
				}
			}
			//不滿足到達條件進入下次循環,等待進程到達
			if (temp == NUMBER - i - 1){
				if (i < NUMBER - 1){
					i--;
					temp_sum++;
					continue;
				}
			}

			//計算優先級
			for (int j = i; j < NUMBER; j++) {
				name_server_psa[j].prioprity = (name_server_psa[i - 1].finished - name_server_psa[j].arrive_time + name_server_psa[j].server_time)/ (name_server_psa[j].server_time*1.0);
			}
			//找出當次循環的最大優先級
			name_server max = name_server_psa[i];
			int max_index = i;
			for (int j = i + 1; j < NUMBER; j++) {
				//判斷是否到達
				if (name_server_psa[i].arrive_time > temp_sum){
					//前移最大優先級
					if (j == NUMBER-1) {
						//交換位置
						chang_position(name_server_psa, max_index, i);
					}
					continue;
				}

				if (max.prioprity < name_server_psa[j].prioprity) {
					max = name_server_psa[j];
					max_index = j;
				}

				//前移最大優先級
				if (j == NUMBER-1) {
					//交換位置
					chang_position(name_server_psa, max_index, i);
				}
			}
			//計算完成時間
			name_server_psa[i].finished = temp_sum + name_server_psa[i].server_time;
			temp_sum += name_server_psa[i].server_time;
		}
	}

	//恢復進程名的順序
	name_server new_name_server_psa[NUMBER];
	recovery_order(new_name_server_psa, name_server_psa);

	//計算帶輸出
	calc_work_or_a_work(new_name_server_psa);
}

//輪轉調度算法
void rr() {
	name_server name_server_rr[NUMBER];
	init_data(name_server_rr);

	int r_r = 4;

	int finished_circle = 1;
	int circle_times = 1;
	int temp_sum = 0;
	while (finished_circle) {
		finished_circle = 0;
		for (int i = 0; i < NUMBER; i++) {
			//循環遍歷查找是否滿足到達時間
			int temp = 0;
			for (int j = i; j<NUMBER - i; j++){
				if (name_server_rr[j].arrive_time > temp_sum){
					temp++;
				}
			}
			//不滿足到達條件進入下次循環,等待進程到達
			if (temp == NUMBER - i - 1){
				//當不是第一個數據的時候
				if (i != 0){
					if (i < NUMBER - 1){
						i--;
						temp_sum++;
						continue;
					}
				}
				
			}
			if (name_server_rr[i].is_finished == 1) {
				continue;
			}
			//判斷是否出現週期大於服務時間的情況
			if ((name_server_rr[i].server_time - (circle_times - 1)*r_r) <= r_r) {
				temp_sum += (name_server_rr[i].server_time - (circle_times-1)*r_r);
			}
			else{
				temp_sum += r_r;
			}
			//判斷是否爲結束狀態
			if ((circle_times*r_r) >= name_server_rr[i].server_time) {
				name_server_rr[i].is_finished = 1;
				name_server_rr[i].finished = temp_sum;
			}
			//繼續循環
			if (name_server_rr[i].server_time > (circle_times*r_r)) {
				finished_circle = 1;
			}
		}
		circle_times++;
	}

	//計算帶輸出
	calc_work_or_a_work(name_server_rr);

}

//多級反饋隊列
void mfq() {
	//用於最後存儲完成時間和計算使用
	name_server copy_name_server_mfq[NUMBER];
	//用於計算操作使用
	name_server name_server_mfq[NUMBER];
	init_data(copy_name_server_mfq);
	init_data(name_server_mfq);

	int r_r = 1;
	int temp_sum = 0;
	int num_queue = 0;
	while (true) {
		if (temp_sum != 0){
			r_r *= 2;
		}
		printf("----------------------\n");
		num_queue++;
		printf("%d隊列:\n", num_queue);
		int temp = 0;
		for (int i = 0; i<NUMBER; i++) {

			//循環遍歷查找是否滿足到達時間
			int is_temp = 0;
			for (int j = i; j<NUMBER - i; j++){
				if (name_server_mfq[j].arrive_time > temp_sum){
					is_temp++;
				}
			}
			//不滿足到達條件進入下次循環,等待進程到達
			if (is_temp == NUMBER - i - 1){
				//當不是第一個數據的時候
				if (i != 0){
					if (i < NUMBER - 1){
						i--;
						temp_sum++;
						continue;
					}
				}

			}
			//判斷此進程是否運行結束
			if (name_server_mfq[i].server_time == 0) {
				temp++;
				continue;
			}
			//判斷當前時間就進程是否到達
			if (name_server_mfq[i].arrive_time > temp_sum) {
				continue;
			}
			//判斷此進程是否在當前就緒隊列結束
			if (name_server_mfq[i].server_time <= r_r ) {
				temp_sum += name_server_mfq[i].server_time;
				printf("%c進程在此隊列運行%d時間,%c進程運行完畢!\n",
					name_server_mfq[i].process_name, 
					name_server_mfq[i].server_time,
					name_server_mfq[i].process_name);
				name_server_mfq[i].server_time = 0;
				copy_name_server_mfq[i].finished = temp_sum;
			}
			else{
				temp_sum += r_r;
				name_server_mfq[i].server_time -= r_r;
				printf("%c進程在此隊列運行%d時間\n", name_server_mfq[i].process_name, r_r);
			}
		}

		//判斷進程就緒隊列是否爲空
		if (temp == NUMBER) {
			break;
		}
	}
	//計算週轉時間和帶權週轉時間
	calc_work_or_a_work(copy_name_server_mfq);
}

//初始化數據
void init_data(name_server *init_data){
	for (int i = 0; i < NUMBER; i++) {
		init_data[i].process_name = process_name[i];
		init_data[i].arrive_time = arrive_time[i];
		init_data[i].server_time = server_time[i];
		init_data[i].is_finished = 0;
	}
}

//交換位置
void chang_position(name_server *temp_name_server, int index, int temp_value){
	name_server temp = temp_name_server[index];
	temp_name_server[index] = temp_name_server[temp_value];
	temp_name_server[temp_value] = temp;
}

//恢復進程名順序
void recovery_order(name_server *new_name_server, name_server *old_name_server) {
	for (int i = 0; i<NUMBER; i++) {
		new_name_server[old_name_server[i].process_name - 'A'] = old_name_server[i];
	}
}

//計算週轉時間和帶權週轉時間
void calc_work_or_a_work(name_server *new_name_server) {
	double avg_work = 0.0;
	double avg_a_work = 0.0;
	for (int i = 0; i<NUMBER; i++) {
		//週轉時間
		new_name_server[i].work = new_name_server[i].finished - new_name_server[i].arrive_time;
		//總週轉時間
		avg_work += new_name_server[i].work;
		//帶權週轉時間
		new_name_server[i].a_work = (new_name_server[i].work * 1.0) / new_name_server[i].server_time;
		//總帶權週轉時間
		avg_a_work += new_name_server[i].a_work;
	}

	print(new_name_server);
	printf("平均週轉時間:%5.2f\n", avg_work / 5);
	printf("平均帶權週轉時間:%5.2f\n", avg_a_work / 5);
}

//輸出數據
void print(name_server print_struct[NUMBER]){
	printf("進程名 到達時間 服務時間 完成時間 週轉時間 帶權週轉時間\n");
	for (int i = 0; i<NUMBER; i++){
		printf("%c\t%d\t%-7d\t%-8d\t%-d\t%.2f\n", print_struct[i].process_name,
			print_struct[i].arrive_time,
			print_struct[i].server_time,
			print_struct[i].finished,
			print_struct[i].work,
			print_struct[i].a_work);
	}
}

//選項跳轉
void choice_ui(int choice){
	switch (choice) {
	case 1:
		fcfs();
		break;
	case 2:
		sjf();
		break;
	case 3:
		psa();
		break;
	case 4:
		rr();
		break;
	case 5:
		mfq();
		break;
	default:
		printf("輸入有誤!");
	}
	system("pause");
}


void main() {
	int choice;
	while (1) {
		printf("選擇查看的作業調度算法:\n");
		printf("1、先來先服務(fcfs)\n");
		printf("2、短作業優先(sjf)\n");
		printf("3、優先調度算法(psa)\n");
		printf("4、輪轉調度算法(rr)\n");
		printf("5、多級反饋隊列調度算法\n");
		scanf("%d",&choice);
		choice_ui(choice);
		system("cls");
	}
	system("pause");
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章