先到先服务调度、短作业优先调度、时间片轮转调度、优先权调度算法

XATU操作系统第一次实验——进程调度实现


实现以下要求:

  • 有录入界面,动态录入进程个数、时间片大小、创建进程控制块(PCB)通过录入界面录入进程标识符、进程到达时间、服务时间等信息;
  • 有算法选择界面,能够根据需要选择不同调度算法;
  • 有输出界面,能够输出不同调度算法下诸进程的进程标识符、到达时间、服务时间、开始时间、完成时间、周转时间、带权周转时间以及一批作业的平均周转时间、平均带权周转时间;进程调度算法

一、源码

#include<iostream>
#include<assert.h>
#include <map>
using namespace std;

typedef struct PCB
{
	char name[10];//此为进程id
	char state;   //进程状态w/r
	int Arrivetime;//进程到达时间
	int BeginTime;//进程开始时间
	int FinishTime;//进程结束时间
	int  ServerTime;//进程服务时间
	float wholeTime;//周转时间
	float Weight_wholetime;//带权周转时间
	double Average_wholeTime;//平均周转时间
	double Average_weight_wholetime;//带权平均周转时间

	int  RunTime;//已经占用cpu时间
	int  NeedTime;//还需要cpu时间

	int  Prio;//优先级
	struct PCB* next;
}pcb, * Pcb;

int Proc_Num = 0;//进程数目

void head_Show(Pcb proc)//输入打印
{
	assert(proc != NULL);
	printf("  PCB_ID  优先级数  到达时间  服务时间\n");
	while (proc != NULL)
	{
		printf("%6s    %6d    %6d    %6d\n",
			proc->name, proc->Prio,
			proc->Arrivetime, proc->ServerTime);
		proc = proc->next;

	}
}
void Show(Pcb proc)
{
	assert(proc != NULL);
	double sum_wholeTime = 0;
	double sum_weight_wholetime = 0;
	pcb* p = proc;
	while (p != NULL)
	{
		sum_wholeTime += p->wholeTime;
		sum_weight_wholetime += p->Weight_wholetime;
		p = p->next;
	}
	double Average_wholeTim = sum_wholeTime / Proc_Num;
	double Average_weight_wholetime = sum_weight_wholetime / Proc_Num;
	printf("  PCB_ID  到达时间  开始时间  服务时间  完成时间  周转时间  带权周转时间\n");
	while (proc != NULL)
	{
		printf("%6s    %6d    %6d    %6d    %6d    %8.1f    %8.2f\n",
			proc->name,
			proc->Arrivetime, proc->BeginTime, proc->ServerTime,
			proc->FinishTime, proc->wholeTime, proc->Weight_wholetime);
		proc = proc->next;
	}
	printf("  平均周转时间  平均带权周转时间  \n");
	printf("  %10.2f        %10.2f\n", Average_wholeTim,
		Average_weight_wholetime);
}
//创建输入链表——不带头结点的单链表
Pcb PCB_Create()
{
	cout << "请输入进程个数:";
	cin >> Proc_Num;
	pcb* _head = NULL;
	pcb* _tail = NULL;
	if (Proc_Num > 6000)
	{
		return NULL;
	}
	cout << "请输入PCB名称、优先级、到达时间、服务时间" << endl;
	for (int i = 1; i <= Proc_Num; i++)
	{
		pcb* new_proc = (pcb*)malloc(sizeof(pcb));
		assert(NULL != new_proc);
		cin >> new_proc->name >> new_proc->Prio >> new_proc->Arrivetime >> new_proc->ServerTime;
		new_proc->next = NULL;
		new_proc->NeedTime = new_proc->ServerTime;
		new_proc->RunTime = 0;
		new_proc->BeginTime = 0;
		new_proc->FinishTime = 0;
		if (NULL == _head)
		{
			_tail = new_proc;
			_head = new_proc;
		}
		else
		{
			_tail->next = new_proc;
			_tail = new_proc;
		}
	}
	return _head;
}
//时间先后顺序排序
Pcb Sort_Arrivetime(Pcb list)
{
	assert(NULL != list);
	pcb* new_head = (pcb*)malloc(sizeof(pcb));
	assert(NULL != new_head);
	new_head->Arrivetime = 0;
	new_head->ServerTime = 0;
	new_head->next = NULL;
	pcb* head = NULL;
	while (list != NULL)
	{
		pcb* cur = list; //指向当前进程
		list = list->next;
		cur->next = NULL;

		if (new_head->next == NULL)
		{
			new_head->next = cur;
		}
		else
		{
			pcb* ptr = new_head;
			//ptr 移动到指向最后一个进程
			for (ptr; ptr->next != nullptr; ptr = ptr->next);
			//当前进程进入时间大,直接接到最后一个的下一个
			if (cur->Arrivetime >= ptr->Arrivetime)
			{
				ptr->next = cur;

			}
			else
			{
				pcb* p = new_head;
				//p从进程链表里从头遍历,找到当前进程进入时间较已在链表中进程进入时间小的位置
				while (cur->Arrivetime > p->next->Arrivetime)
				{
					p = p->next;
				}
				//插入当前进程
				cur->next = p->next;
				p->next = cur;
			}
		}
	}
	return new_head->next;
}
//短作业排序链表
Pcb Sort_Shortjob(Pcb list)
{
	assert(NULL != list);
	pcb* new_head = (pcb*)malloc(sizeof(pcb));
	assert(NULL != new_head);
	new_head->Arrivetime = 0;
	new_head->ServerTime = 0;
	new_head->next = NULL;
	pcb* head = NULL;
	while (list != NULL)
	{
		pcb* cur = list;
		list = list->next;
		cur->next = NULL;

		if (new_head->next == NULL)
		{
			new_head->next = cur;
		}
		else
		{
			pcb* ptr = new_head;
			for (ptr; ptr->next != nullptr; ptr = ptr->next);

			if (cur->ServerTime >= ptr->ServerTime)
			{
				ptr->next = cur;

			}
			else
			{
				pcb* p = new_head;
				while (cur->ServerTime > p->next->ServerTime)
				{
					p = p->next;
				}
				cur->next = p->next;
				p->next = cur;

			}
		}
	}
	return new_head;
}
PCB* RR_runprocces(PCB* head, int time_slice)//时间片轮转
{
	assert(head != nullptr);
	int _time = head->Arrivetime;
	int flag = 0; //记录未完成的进程数量
	bool tag = false; //表示未被释放,需要放到链尾
	map<char*, int> mp;
	for (pcb* p = head; p != NULL; p = p->next)
	{
		flag++;
		mp.insert (make_pair(p->name, 0));
	}
	//head 为未执行的进程链表
	//新建执行链表 run_head, 不带头结点
	//初始状态只有按进入时间排好的第一个进程
	pcb* run_head = head;
	head = head->next;
	run_head->next = nullptr;

	//新建执行完毕链表 runed_head, 不带头结点
	pcb* runed_head = nullptr;

	while (flag > 0)
	{
		if (run_head == nullptr) //执行链表中的都执行完毕,但还有进程未到
		{
			run_head = head;
			head = head->next;
			run_head->next = nullptr;
			_time = run_head->Arrivetime;
		}
		pcb* ptr = run_head;
		cout << _time << "时刻" << "开始执行: " << ptr->name << endl;

		map<char*, int> ::iterator it = mp.find(ptr->name);
		if (it != mp.end() && it->second == 0)
		{
			it->second = 1;
			ptr->BeginTime = _time;
		}
		
		//运行所需时间小于等于时间片
		if (ptr->NeedTime <= time_slice)
		{
			_time += ptr->NeedTime < time_slice ? ptr->NeedTime : time_slice;
			//执行完毕
			cout << _time << "时刻" << ptr->name << "执行完毕" << endl;
			cout << endl;
			flag--;
			ptr->state = 'P';
			ptr->FinishTime = _time;
			//移到已执行完毕链表 或
			//直接销毁
			pcb* des = run_head;
			run_head = run_head->next;
			des->next = nullptr;
			//free(des);
			//des = nullptr;
			if (runed_head == nullptr)
			{
				runed_head = des;
			}
			else
			{
				pcb* ped = runed_head;
				for (; ped->next != nullptr; ped = ped->next); //ped 指向最后一个进程
				ped->next = des;
			}		
			tag = true;
		}
		else
		{	//未执行完毕,时间片结束
			_time += time_slice;
			//修改该进程的信息
			ptr->RunTime += time_slice; //已执行时长
			ptr->NeedTime = ptr->ServerTime - ptr->RunTime; //还需CPU时长
			if (ptr->NeedTime > 0)
			{
				cout << "时刻:" << _time<< "\t挂起作业:" << ptr->name;
				cout << "\t已运行:" << ptr->RunTime << "\t还需要执行:" << ptr->NeedTime << endl;
				cout << endl;		
			}
		}
		//遍历未执行进程链表,将当前时间到达的进程放入执行链表
		for (head; head != nullptr; )
		{
			if (head->Arrivetime <= _time)
			{
				pcb* q = head;
				//从原未执行链表移出
				head = head->next;
				q->next = nullptr;
				//采用尾插法放入执行链表
				pcb* p = run_head;
				if (run_head == nullptr)
					run_head = q;
				else
				{
					for (; p->next != nullptr; p = p->next); //p 指向最后一个进程
					p->next = q;
				}
			}
			//未执行进程链表是按照到达时间排好的,后面的只会越来越晚
			else
				break;
		}
		if (tag == true) //被释放
		{
			tag = false;
			continue;
		}
		//当前进程挂到执行队列尾
		pcb* p = run_head;
		for (; p->next != nullptr; p = p->next); //p 指向最后一个进程
		pcb* p1 = run_head;
		run_head = run_head->next;
		p1->next = nullptr;
		p->next = p1;

	}
	//补全周转时间和带权周转时间等
	for (pcb* s = runed_head; s != nullptr; s = s->next)
	{
		s->wholeTime = s->FinishTime - s->Arrivetime;
		s->Weight_wholetime = s->wholeTime / s->ServerTime;
	}
	return runed_head;
}
Pcb End_list(Pcb plist)//最终链表
{
	assert(NULL != plist);
	int begin_time = plist->Arrivetime; //起始时间为第一个的到达时间
	plist->BeginTime = begin_time;
	int end_time = begin_time + plist->ServerTime;
	plist->FinishTime = end_time;
	plist->wholeTime = (float)(plist->FinishTime - plist->Arrivetime);
	plist->Weight_wholetime = (float)(plist->wholeTime / plist->ServerTime);
	plist->state = 'W';
	plist->RunTime = 0;
	pcb* ptr = plist->next;
	while (ptr != NULL)
	{
		//上一个进程结束,但下一个未到
		if (ptr->Arrivetime > end_time)
		{
			end_time = ptr->Arrivetime;
		}
		ptr->BeginTime = end_time;
		ptr->FinishTime = end_time + ptr->ServerTime;
		end_time += ptr->ServerTime;
		ptr->wholeTime = (float)(ptr->FinishTime - ptr->Arrivetime);
		ptr->Weight_wholetime = (float)(ptr->wholeTime / ptr->ServerTime);
		ptr->state = 'W';
		ptr->RunTime = 0;
		ptr = ptr->next;
	}

	return plist;
}
Pcb Sort_SJFjob(Pcb list, int time)
{
	assert(NULL != list);
	//先按照服务时间进行排序——服务时长链表,带头结点
	pcb* ptr_head = Sort_Shortjob(list);
	//创建进程已执行链表
	pcb* head_node = (pcb*)malloc(sizeof(pcb));
	assert(head_node != NULL);
	head_node->Arrivetime = 0;
	head_node->ServerTime = 0;
	head_node->Prio = 0;
	head_node->next = NULL;
	//链表不为空,表明还有进程未执行
	while (ptr_head->next != NULL)
	{
		//a 指向服务时长链表中第一个进程
		pcb* a = ptr_head->next;
		if (a->next == NULL) //仅有一个进程,直接放入执行链表
		{
			//tail 指向进程执行链表的最后一个进程
			pcb* tail = head_node;
			for (tail; tail->next != NULL; tail = tail->next);
			//放入仅剩的一个进程
			tail->next = a;
			ptr_head->next = NULL;
		}
		else //服务时长链表中未执行的进程不止一个
		{
			//找一个进程的进入时间小于当前时间直至最后一个
			while (a->Arrivetime > time && a->next != NULL)
			{
				a = a->next;
			}
			//所有服务时长链表中未执行的进程在当前时间都为进入
			if (a->next == NULL && a->Arrivetime > time)
			{
				pcb* e = ptr_head->next;
				//销毁原按照服务时长排序的链表
				ptr_head->next = NULL;
				free(ptr_head);
				//重新按照到达时间排序,在所有未进入的中选最先进入的
				pcb* d = Sort_Arrivetime(e);
				// s指向最先进入的进程
				pcb* s = d->next;
				d->next = NULL;
				//变更当前时间
				time = time + d->ServerTime;

				//将最先进入的进程d,放入进程已执行链表
				pcb* tail = head_node;
				for (tail; tail->next != NULL; tail = tail->next);
				tail->next = d;
				//对剩下的再次服务时间排序,为下次按照服务时间放入已执行链表做准备
				ptr_head = Sort_Shortjob(s);

			}
			//在当前时间下,服务时长链表中存在进程到达时间较小,即已经到达,要放入执行链表
			else
			{
				//在服务时长链表找到已经到达的进程a的前驱
				pcb* c = ptr_head;
				while (c->next != a)
				{
					c = c->next;
				}
				//将进程a摘除
				c->next = a->next;
				a->next = NULL;
				//变更当前时间
				time = time + a->ServerTime;
				//将进程a放到已执行链表
				pcb* tail = head_node;
				for (tail; tail->next != NULL; tail = tail->next);
				tail->next = a;
			}
		}

	}
	//返回已执行链表,不带头结点
	pcb* back_head = head_node->next;
	head_node->next = NULL;
	free(head_node);
	head_node = NULL;
	return back_head;
}
Pcb Sort_SJF(Pcb list)
{
	assert(list != NULL);
	//首先按照到达时间排好链表(无头结点)
	pcb* head = Sort_Arrivetime(list);
	int _time = head->Arrivetime;
	if (head->next != NULL)
	{	
		pcb* _head = Sort_SJFjob(head, _time);
		head = _head;
	}
	return head;
}
//按优先级排序
Pcb Sort_PRC(Pcb list)
{
	assert(NULL != list);
	pcb* new_head = (pcb*)malloc(sizeof(pcb));
	assert(NULL != new_head);
	new_head->Arrivetime = 0;
	new_head->ServerTime = 0;
	new_head->Prio = 0;
	new_head->next = NULL;
	pcb* head = NULL;
	while (list != NULL)
	{
		pcb* cur = list;
		list = list->next;
		cur->next = NULL;
		if (new_head->next == NULL)
		{
			new_head->next = cur;
		}
		else
		{
			pcb* ptr = new_head;
			for (ptr; ptr->next != nullptr; ptr = ptr->next);

			if (ptr->Prio >= cur->Prio)
			{
				ptr->next = cur;

			}
			else
			{
				pcb* p = new_head;
				while (p->next->Prio > cur->Prio)
				{
					p = p->next;
				}
				cur->next = p->next;
				p->next = cur;

			}
		}
	}
	return new_head;
}
Pcb Sort_PrcjobNB(Pcb list, int time)
{
	assert(NULL != list);
	//先按照优先级进行排序——优先级链表,带头结点
	pcb* ptr_head = Sort_PRC(list);
	//创建进程已执行链表
	pcb* head_node = (pcb*)malloc(sizeof(pcb));
	assert(head_node != NULL);
	head_node->Arrivetime = 0;
	head_node->ServerTime = 0;
	head_node->Prio = 0;
	head_node->next = NULL;
	//链表不为空,表明还有进程未执行
	while (ptr_head->next != NULL)
	{
		//a 指向优先级链表中第一个进程
		pcb* a = ptr_head->next;
		if (a->next == NULL) //仅有一个进程,直接放入执行链表
		{
			//tail 指向进程执行链表的最后一个进程
			pcb* tail = head_node;
			for (tail; tail->next != NULL; tail = tail->next);
			//放入仅剩的一个进程
			tail->next = a;
			ptr_head->next = NULL;
		}
		else //优先级链表中未执行的进程不止一个
		{
			//找一个进程的进入时间小于当前时间直至最后一个
			while (a->Arrivetime > time && a->next != NULL)
			{
				a = a->next;
			}
			//所有优先级链表中未执行的进程在当前时间都未进入
			if (a->next == NULL && a->Arrivetime > time)
			{
				pcb* e = ptr_head->next;
				//销毁原按照优先级排序的链表
				ptr_head->next = NULL;
				free(ptr_head);
				//重新按照到达时间排序,在所有未进入的中选最先进入的
				pcb* d = Sort_Arrivetime(e);
				// s指向最先进入的进程
				pcb* s = d->next;
				d->next = NULL;
				//变更当前时间
				time = time + d->ServerTime;

				//将最先进入的进程d,放入进程已执行链表
				pcb* tail = head_node;
				for (tail; tail->next != NULL; tail = tail->next);
				tail->next = d;
				//对剩下的再次优先级排序,为下次按照服务时间放入已执行链表做准备
				ptr_head = Sort_PRC(s);

			}
			//在当前时间下,优先级链表中存在进程到达时间较小,即已经到达,要放入执行链表
			else
			{
				//在优先级链表找到已经到达的进程a的前驱
				pcb* c = ptr_head;
				while (c->next != a)
				{
					c = c->next;
				}
				//将进程a摘除
				c->next = a->next;
				a->next = NULL;
				//变更当前时间
				time = time + a->ServerTime;
				//将进程a放到已执行链表
				pcb* tail = head_node;
				for (tail; tail->next != NULL; tail = tail->next);
				tail->next = a;
			}
		}
	}
	//返回已执行链表,不带头结点
	pcb* back_head = head_node->next;
	head_node->next = NULL;
	free(head_node);
	head_node = NULL;
	return back_head;
}
Pcb Sort_Prc(Pcb list)
{
	assert(list != NULL);
	pcb* head = Sort_Arrivetime(list);
	int _time = head->Arrivetime;
	if (head->next != NULL)
	{
		head = Sort_PrcjobNB(head, _time);
	}
	return head;
}
void FCFS()//先来先服务
{
	//创建进程队列
	pcb* head = PCB_Create();
	printf("\t\t算法调度前如下:\n");
	head_Show(head);
	putchar('\n');
	printf("\t\t\t\t算法调度后如下:\n");
	//按进程到达时间排序
	pcb* end_head = Sort_Arrivetime(head);
	struct PCB* list = End_list(end_head);
	Show(list);
}
//短作业优先
void SJF()
{
	pcb* head = PCB_Create();
	printf("\t\t算法调度前如下:\n");
	head_Show(head);
	putchar('\n');
	printf("\t\t\t\t算法调度后如下:\n");
	pcb* end = Sort_SJF(head);
	pcb* list = End_list(end);
	Show(list);
}
//优先级调度
void PrioCreate()
{
	pcb* head = PCB_Create();
	printf("\t\t算法调度前如下:\n");
	head_Show(head);
	putchar('\n');
	printf("\t\t\t\t算法调度后如下:\n");
	pcb* end = Sort_Prc(head);
	pcb* list = End_list(end);
	Show(list);
}
//时间片轮转算法
void RR()
{
	int time_slice;
	cout << "输入时间片:";
	cin >> time_slice;
	pcb* head = PCB_Create();
	printf("\t\t算法调度前如下:\n");
	head_Show(head);
	putchar('\n');
	printf("\t\t\t\t算法调度后如下:\n");
	pcb* end_head = Sort_Arrivetime(head);

	PCB* runed_head = RR_runprocces(end_head, time_slice);
	Show(runed_head);
}
int main()
{
	int select = 1;
	while (select)
	{
		cout << "******************************************\n";
		cout << "*****1.******* 先来先服务算法 ************\n";
		cout << "*****2.********  短作业优先   ************\n";
		cout << "*****3.********  时间片轮转   ************\n";
		cout << "*****4.********  优先级调度   ************\n";
		cout << "*****0.**********退出*********************\n";

		cout << "请选择:> ";
		cin >> select;
		switch (select)
		{
		case 1:
			//先来先服务
			FCFS();
			break;
		case 2:
			//短作业优先
			SJF();
			break;
		case 3:
			//时间片轮转
			RR();
			break;
		case 4:
			//优先级调度
			PrioCreate();
			break;
		default:
			break;

		}
	}
	return 0;
}


二、测试与执行结果

1、先到先服务:
测试用例:
在这里插入图片描述

执行结果:
在这里插入图片描述

2、短作业优先算法
测试用例:

在这里插入图片描述

执行结果:
在这里插入图片描述

3、时间片轮转
测试用例:
在这里插入图片描述

执行结果:
在这里插入图片描述
在这里插入图片描述

4、优先级调度
测试用例:
在这里插入图片描述

执行结果:
在这里插入图片描述

有问题请联系QQ:1213403737(大牛)
(学妹优先👻)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值