操作系统课程实验1-进程调度模拟实验

操作系统课程实验1-进程调度模拟实验

一、实验介绍

1.1 实验目的

本实验模拟在单处理机环境下的处理机调度,帮助理解进程调度的概念,深入了解进程控制块的功能,以及进程的创建、撤销和进程各个状态间的转换过程。

1.2 实验内容
  1. 进程调度算法:采用最高优先数优先的调度算法、先来先服务算法、SJF和多级反馈调度算法。
  2. 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为输入(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。
1.3 实验要求
  1. 每进行一次调度程序都显示输出一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
  2. 对同一组进程的各种调度算法分别计算平均周转时间和平均带权周转时间。
1.4 参考测试数据

系统有5个进程,其就绪时刻、服务时间和优先级(优先级数值越大优先级越高)如下图所示:
在这里插入图片描述

多级反馈队列调度算法:设3个就绪队列,时间片分别为1、2、3。

二、实现代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

typedef struct ProcessControlBlock { // 定义进程控制块结构体
	int name;                   // 进程名称
	unsigned int Arrive_Time;   // 到达时间
	unsigned int Wait_Time;     // 等待时间
	unsigned int Start_Time;    // 开始时间
	unsigned int Serve_Time;    // 服务时间
	unsigned int Finish_Time;   // 完成时间
	int Priority;               // 优先级
	unsigned int cycle_time;    // 周转时间
	double Weighted_cycle_time; // 带权周转时间
	unsigned int Original_Serve_Time;
	bool FinishFlag;            // 完成标志
} PCB;                          // 进程控制块的别名

typedef struct Multilevel_Feedback_Queue { // 定义多级反馈队列
	int L1_Length, L1[5];       // 第一级别反馈队列
	int L2_Length, L2[5];       // 第二级别反馈队列
	int L3_Length, L3[5];       // 第三级别反馈队列
	unsigned int Time_Slice[3]; // 三级反馈队列分配的时间片
} MFQ;



void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]); 					 	// 函数声明:输入进程控制块信息

void Highest_Prioriy_First(PCB  Process[5]); 	// 函数声明:最高优先级优先算法
void First_Come_First_Serve(PCB Process[5]); 	// 函数声明:先来先服务算法
void Shortest_Job_First(PCB Process[5]);	 	// 函数声明:短作业优先算法
void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]);	// 函数声明:多级反馈队列算法
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ * mfq);	// 函数声明:多级反馈队列的输入

bool SortBy_Priority(PCB* a, PCB* b);		 	// 函数声明:按优先级排序
bool SortBy_ServeTime(PCB* a, PCB* b);		 	// 函数声明:按服务时间排序
bool SortBy_ArriveTime(PCB a, PCB b);		 	// 函数声明:按到达时间排序


int main(void) {
	PCB Process_HPF[5]; 								// 定义5个进程控制块数组
	PCB Process_FCFS[5]; 								// 定义5个进程控制块数组
	PCB Process_SJF[5]; 								// 定义5个进程控制块数组
	PCB Process_MFQ[5]; 								// 定义5个进程控制块数组
	PCB_Info_Input(Process_HPF, Process_FCFS, Process_SJF, Process_MFQ); 								// 调用输入进程控制块信息函数
	Highest_Prioriy_First(Process_HPF); 				// 调用优先级最高优先算法函数
	First_Come_First_Serve(Process_FCFS); 				// 调用先来先服务算法函数
	Shortest_Job_First(Process_SJF);	 				// 调用短作业优先算法函数
	Multilevel_Feedback_Queue_Algorithm(Process_MFQ); 	// 调用多级反馈队列调度算法

	return 0;
}

//	3比较函数,用于sort函数的参数
bool SortBy_ArriveTime(PCB a, PCB b) {
	return a.Arrive_Time < b.Arrive_Time;
}
bool SortBy_Priority(PCB* a, PCB* b) {
	return a->Priority < b->Priority;
}
bool SortBy_ServeTime(PCB* a, PCB* b) {
	return a->Serve_Time < b->Serve_Time;
}


void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]) {
	cout << "\nPlease input the Process Control Block information\n" << endl;
	for (int i = 0; i < 5; i++) {
		printf("PCB%d:", i);
		scanf("%u%u%d", &Process_HPF[i].Arrive_Time, &Process_HPF[i].Serve_Time, &Process_HPF[i].Priority);
		// 完成输入的深拷贝
		Process_FCFS[i].Arrive_Time = Process_SJF[i].Arrive_Time = Process_MFQ[i].Arrive_Time = Process_HPF[i].Arrive_Time;
		Process_FCFS[i].Serve_Time = Process_SJF[i].Serve_Time = Process_MFQ[i].Serve_Time = Process_HPF[i].Serve_Time;
		Process_FCFS[i].Priority = Process_SJF[i].Priority = Process_MFQ[i].Priority = Process_HPF[i].Priority;

		Process_HPF[i].name = Process_FCFS[i].name = Process_SJF[i].name = Process_MFQ[i].name = i + 1; 							// 设置进程名称
		Process_HPF[i].FinishFlag = Process_FCFS[i].FinishFlag = Process_SJF[i].FinishFlag = Process_MFQ[i].FinishFlag = false; 	// 初始化完成标志为false
	}
}

// 优先级最高优先调度算法函数
void Highest_Prioriy_First(PCB Process[5]) {

	cout << "\n优先级最高优先调度算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime);  // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 						// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 									// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { 				// 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { // 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 							 // 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按优先级进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_Priority);
		// 选取优先级最大的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tPriority:" << Available_Processes[0]->Priority
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 先来先服务调度算法(FCFS)
void First_Come_First_Serve(PCB  Process[5]) {

	cout << "\n先来先服务调度算法:" << endl;
	int FinishCout = 0; 	// 完成进程计数器初始化为0
	unsigned Time = 0; 		// 时间初始化为0
	cout << endl;
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { // 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = -1; 		 // 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) {
				j = i;
				break;
			}
		}
		// 如果j为-1,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == -1) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 选取当前满足条件且到达时间最早的进程进行执行
		Process[j].Start_Time = Time; 	// 设置进程开始时间
		Process[j].Wait_Time = Process[j].Start_Time - Process[j].Arrive_Time; // 设置进程等待时间
		Time += Process[j].Serve_Time; 	// 更新时间
		Process[j].Finish_Time = Time; 	// 设置进程完成时间
		Process[j].cycle_time = Process[j].Finish_Time - Process[j].Arrive_Time; 				// 计算进程周转时间
		Process[j].Weighted_cycle_time = Process[j].cycle_time * 1.0 / Process[j].Serve_Time;
		Process[j].FinishFlag = true; 	// 设置进程完成标志为true

		cout << "PCB:" << Process[j].name << "\tArriveTime:" << Process[j].Arrive_Time
		     << "\tWaitTime:" << Process[j].Wait_Time
		     << "\tStartTime:" << Process[j].Start_Time
		     << "\tServeTime:" << Process[j].Serve_Time
		     << "\tFinishTime:" << Process[j].Finish_Time
		     << "\tCircleTime:" << Process[j].cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; // 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 短作业优先算法 (SJF)
void Shortest_Job_First(PCB Process[5]) {

	cout << "\n短作业优先算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 	// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 				// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { 	// 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 								// 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按服务时间进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_ServeTime);
		// 选取当前满足条件且服务时间最短的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间

}

void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]) {
	cout << "\n多级反馈队列调度算法:" << endl;
	MFQ MFQSet;
	Multilevel_Feedback_Queue_Algorithm_Input(&MFQSet); // 调用输入多级反馈队列的函数
	queue<PCB> L1, L2, L3; // 定义三个队列
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	unsigned int Time = 0; // 时间初始化为0
	double avg = 0, weighted_avg = 0; // 初始化平均周转时间和带权平均周转时间
	for (int i = 0; i < 5; i++) { // 将进程按照到达时间加入到第一级别队列
		Process[i].Original_Serve_Time = Process[i].Serve_Time;
		L1.push(Process[i]);

	}
	while (!L1.empty() || !L2.empty() || !L3.empty()) { // 当三个队列有不为空的时循环
		cout << "Time:" << Time << " \t\t"; // 输出当前时间
		if (!L1.empty()) { // 如果第一级别队列不为空
			PCB temp = L1.front(); // 获取队首进程
			L1.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[0]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[0])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列2的末尾\n";
				L2.push(temp); // 否则将当前进程加入到第二级别队列
			}
		} else if (!L2.empty()) { // 如果第一级别队列为空但第二级别队列不为空
			PCB temp = L2.front(); // 获取队首进程
			L2.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[1]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[1])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列3的末尾\n";
				L3.push(temp); // 否则将当前进程加入到第三级别队列
			}
		} else { // 如果第一级别和第二级别队列均为空
			while (!L3.empty()) {
				PCB temp = L3.front(); // 获取队首进程
				L3.pop();              // 弹出队首进程
				cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
				Time += min(temp.Serve_Time, MFQSet.Time_Slice[2]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
				temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[2])); // 更新当前进程的服务时间
				if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
					temp.Finish_Time = Time; // 设置当前进程的完成时间
					temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
					temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
					avg += temp.cycle_time;     // 计算总周转时间
					weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
					cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
				} else {
					cout << 'P' << temp.name << "继续执行\n";
					L3.push(temp); // 将当前进程加入到第三级别队列末尾
				}
			}
		}
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转
}



// 输入多级反馈队列的函数
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ *mfq) {
	cout << "Please input the Time Slice(Three Numbers) for Multilevel Feedback Queue" << endl;
	cin >> mfq->Time_Slice[0] >> mfq->Time_Slice[1] >> mfq->Time_Slice[2];
}

三、心灵的救赎

  1. “爱”就是科学与逻辑永远无法解释的程序
    在这里插入图片描述
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统进程调度操作系统最核心的功能之一,是管理计算机系统资源的关键。Java 作为一门跨平台的编程语言,具备丰富的库和易于扩展的特性,可以很好地用于模拟操作系统进程调度。 本次课程设计旨在通过动态模拟操作系统进程调度,使学生对操作系统进程调度的原理、算法和实现有更深刻的理解。课程设计的主要内容包括以下几个方面: 1. 进程调度算法的研究。该阶段需要学生对进程调度算法进行深入研究,包括常见的算法如 FCFS、RR、SPN、SRT 等,还可以考虑一些高级的算法,如多级反馈队列算法等。 2. 系统架构的设计。该阶段需要学生设计操作系统进程调度的各个模块,包括进程管理模块、进程调度模块等。此外,还需要设计用户界面,使得学生可以通过操作界面进行进程的创建、执行和回收等操作。 3. 动态模拟的实现。该阶段是本课程设计的重点,需要学生使用 Java 语言编写程序,实现进程调度算法的动态模拟。学生需要考虑多个进程并发执行时的问题,如进程的度、CPU 切换等。同时,学生还需要考虑系统中资源的竞争和分配问题,如内存分配、磁盘 IO 等。 4. 实验结果分析。该阶段需要学生通过对程序的运行结果进行分析,获得对进程调度算法性能的评估,以及对系统资源利用率的评估。此外,学生还可以通过对不同进程调度算法的比较,掌握进程调度算法的优缺点。 总之,本次课程设计通过动态模拟操作系统进程调度,使学生深入了解进程调度算法的实现和原理,提高了学生的编程能力和试技巧,为学生今后从事操作系统相关工作打下了坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值