操作系统实验一(进程调度算法)

进程调度算法详解

今日闲来无聊,发现很早之前写的操作系统实验还没有整理,再加上有很多人问,索性就发成博客吧。

实验一 进程调度算法
一、实验目的
  用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解.
二、实验指导
设计一个有 N个进程共行的进程调度程序。
  进程调度算法:分别采用先来先服务算法、短作业优先算法、高响应比优先算法实现。
  每个进程用一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先级、到达时间、要求服务时间、进程状态等等。 其中到达时间和要求服务时间可以在程序中进行初始化或者在程序开始时由键盘输入。
  每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
  每个进程完成后要打印该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组进程完成后要计算并打印这组进程的平均周转时间、带权平均周转时间。
三、提示
1、在采用短作业优先算法和高响应比优先算法进行调度时应注意进程的到达时间,对于没有到达的进程不应参与调度。
2、注意在采用高响应比优先算法时计算优先权的时机,因为采用动态优先权,所以应在每次调度之前都重新计算优先权,高响应比优先算法采用下列公式计算优先权在这里插入图片描述
在这里插入图片描述 进程调度算法流程图

#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
struct PCB
{
	string name;
	int arrive_time;
	int service_time;
	int exit_time;
	int wait_time;
	double quan;
	bool ifrun;
	int RR_time;
} pcb[10];
queue<PCB> q;
PCB Que[100];
PCB MQ[50][50];
PCB fcfs[10];
PCB sjf[10];
PCB hrrn[10];
PCB rr[10];
PCB mfq[10];
int top=0;
bool cmpSJF(PCB a,PCB b)
{
	return a.service_time<b.service_time;
}

bool cmpHRRN(PCB a,PCB b)
{
	return a.quan>b.quan;
}
void menu()
{
	printf("进程调度模拟程序\n\n");
	printf("1. 输入作业情况\n\n");
	printf("2. 显示作业情况\n\n");
	printf("3. 先来先服务算法\n\n");
	printf("4. 短作业优先算法\n\n");
	printf("5. 高响应比优先算法\n\n");
	printf("6. 时间片轮转算法\n\n");
	printf("7. 多级反馈队列调度\n\n");
	printf("8. 算法结果对比\n\n");
	printf("0. 退出\n\n");
}
void init()
{
	pcb[0]= {"A",0,3,0,0,0,false,0};
	pcb[1]= {"B",2,6,0,0,0,false,0};
	pcb[2]= {"C",4,4,0,0,0,false,0};
	pcb[3]= {"D",6,5,0,0,0,false,0};
	pcb[4]= {"E",8,2,0,0,0,false,0};
}
void input()
{
	for(int i=0; i<5; i++)
	{
		printf("进程%d:\n",i);
		printf("请输入进程名称:");
		cin>>pcb[i].name;
		printf("请输入到达时间:");
		cin>>pcb[i].arrive_time;
		printf("请输入服务时间:");
		cin>>pcb[i].service_time;
		printf("\n");
	}
}
void display()
{
	printf("名称");
	printf("     ");
	for(int i=0; i<=4; i++)
		cout<<pcb[i].name<<" ";
	printf("\n到达时间 ");
	for(int i=0; i<=4; i++)
		cout<<pcb[i].arrive_time<<" ";
	printf("\n服务时间 ");
	for(int i=0; i<=4; i++)
		cout<<pcb[i].service_time<<" ";
	printf("\n");
	system("pause");
}

void output(PCB a[])
{
	int sumzhou = 0;
	double sumdai = 0;
	printf("名称\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间\n");
	for(int i=0; i<=4; i++)
	{
		cout<<a[i].name<<"\t";
		printf("%d\t\t%d\t\t%d\t\t%d\t\t%.2f\n",a[i].arrive_time,a[i].service_time,a[i].exit_time,a[i].exit_time-a[i].arrive_time,(a[i].exit_time*1.0-a[i].arrive_time)/a[i].service_time*1.0);
	}
	for(int i=0; i<=4; i++)
	{
		sumzhou+=a[i].exit_time-a[i].arrive_time;
		sumdai+=(a[i].exit_time*1.0-a[i].arrive_time)/a[i].service_time*1.0;
	}
	printf("平均周转时间:%.2f   平均带权周转时间:%.2f",sumzhou*1.0/5,sumdai/5);
	system("pause");
}
void outputQue(int front,int rear)
{
	
	printf("\t当前就绪队列: " );
	for(int i=front; i<rear; i++)
	{
		cout<<Que[i].name;
	}
	cout<<endl;
}
void outputMQ(int index,int front[],int rear[])
{
	cout<<endl;
	for(int i=0; i<index; i++)
	{
		
		printf("\t%d级队列:",i+1);
		for(int j=front[i]; j<rear[i]; j++)
		{
			cout<<MQ[i][j].name;
			
		}
		cout<<endl;
	}
	cout<<endl<<endl;
}
void outsum()
{
	cout<<"先来先服务:"<<endl;
	output(fcfs);
	cout<<"短作业优先:"<<endl;
	output(sjf);
	cout<<"高响应比:"<<endl;
	output(hrrn);
	cout<<"时间片轮转:"<<endl;
	output(rr);
	cout<<"多级反馈队列:"<<endl;
	output(mfq);
}
void FCFS()
{
	top=0;
	PCB p= {"0",0,0,0};
	int now = 0;
	int flag = 0; //0空闲 1运行
	int r=0;
	while(1)
	{
		//printf("%d\n",now);
		//如果当前空闲,并且不是第一次空闲,说明有进程执行完毕
		if(flag == 0&&p.name!="0")
		{
			cout<<now<<" "<<p.name<<"执行完毕"<<endl;
			p.ifrun = true;
			fcfs[top++]=p;
		}
		//如果进程全部执行完
		if(top == 5)
			break;
		//查看这一秒是否有进程到达
		for(int i=r; i<5; i++)
		{
			if(pcb[i].arrive_time == now)   //此时间有进程到达
			{
				q.push(pcb[i]); //入队
				cout<<now<<" "<<pcb[i].name<<"到达"<<endl;
				r=i+1;
			}
		}
		if(flag == 0&&!q.empty())   //空闲
		{
			//取队头执行
			p = q.front();
			q.pop();
			cout<<now<<" "<<p.name<<"开始执行"<<endl;
			p.exit_time = p.service_time+now;
			flag = p.service_time;
		}
		//下一秒
		now++;
		if(flag>0)
			flag--;
		Sleep(500);
	}
	output(fcfs);
}

void SJF()
{
	top = 0;
	int front = 0;
	int rear = 0;
	PCB p= {"0",0,0,0};
	int now = 0;
	int flag = 0; //0空闲 1运行
	int r=0;
	while(1)
	{
		//printf("%d\n",now);
		//如果当前空闲,并且不是第一次空闲,说明有进程执行完毕
		if(flag == 0&&p.name!="0")
		{
			cout<<now<<" "<<p.name<<"执行完毕"<<endl;
			p.ifrun = true;
			sjf[top++]=p;
		}
		//如果进程全部执行完
		if(top == 5)
			break;
		//查看这一秒是否有进程到达
		for(int i=r; i<5; i++)
		{
			if(pcb[i].arrive_time == now)   //此时间有进程到达
			{
				Que[rear++]=pcb[i]; //入队
				cout<<now<<" "<<pcb[i].name<<"到达"<<endl;
				sort(Que+front,Que+rear,cmpSJF);
				r=i+1;
			}
		}
		if(flag == 0&&front!=rear)   //空闲
		{
			//取队头执行
			p = Que[front++];
			cout<<now<<" "<<p.name<<"开始执行"<<endl;
			p.exit_time = p.service_time+now;
			flag = p.service_time;
		}
		//下一秒
		now++;
		if(flag>0)
			flag--;
		Sleep(500);
	}
	output(sjf);
}

void HRRN()
{
	top = 0;
	int front = 0;
	int rear = 0;
	PCB p= {"0",0,0,0};
	int now = 0;
	int flag = 0; //0空闲 1运行
	int r=0;
	while(1)
	{
		//printf("%d\n",now);
		//如果当前空闲,并且不是第一次空闲,说明有进程执行完毕
		if(flag == 0&&p.name!="0")
		{
			cout<<now<<" "<<p.name<<"执行完毕"<<endl;
			p.ifrun = true;
			hrrn[top++]=p;
		}
		//如果进程全部执行完
		if(top == 5)
			break;
		//查看这一秒是否有进程到达
		for(int i=r; i<5; i++)
		{
			if(pcb[i].arrive_time == now)   //此时间有进程到达
			{
				cout<<now<<" "<<pcb[i].name<<"到达"<<endl;
				Que[rear++]=pcb[i]; //入队
				r=i+1;
			}
		}
		if(flag == 0&&front!=rear)   //空闲
		{
			//计算优先权并排序
			for(int j=front; j<rear; j++)
				Que[j].quan = (Que[j].wait_time*1.0+Que[j].service_time)/Que[j].service_time;
			sort(Que+front,Que+rear,cmpHRRN);
			//取队头
			p = Que[front++];
			cout<<now<<" "<<p.name<<"开始执行"<<endl;
			p.exit_time = p.service_time+now;
			flag = p.service_time;
		}
		//下一秒
		now++;
		for(int i = front; i<rear; i++)
		{
			Que[i].wait_time++;
		}
		if(flag>0)
			flag--;
		Sleep(500);
	}
	output(hrrn);
}

void RR()
{
	int t=0;
	top = 0;
	int front = 0;
	int rear = 0;
	PCB p= {"0",0,0,0};
	int now = 0;
	int flag = 0; //0空闲 1运行
	int r=0;
	int time;
	printf("请输入时间片间隔:");
	scanf("%d",&time);
	while(1)
	{
		if(t == time)//时间片用完
			t=0;
		//扫描入队
		for(int i=r; i<5; i++)
		{
			if(pcb[i].arrive_time == now)   //此时间有进程到达
			{
				cout<<now<<" "<<pcb[i].name<<"到达"<<endl;
				Que[rear++]=pcb[i]; //入队
				outputQue(front,rear);
				r=i+1;
			}
		}
		if(p.name!="0") //不是第一次
		{
			if(p.RR_time >= p.service_time)//如果已经完成服务
			{
				cout<<now<<" "<<p.name<<" "<<"结束!"<<endl;
				p.exit_time=now;
				t=0;
				rr[top++]=p;
				if(top == 5)
					break;
				p.name="0";
			}
			else if(t == 0) //如果没有完成并且时间片用完了
			{
				cout<<now<<" "<<p.name<<" "<<"时间片用完!"<<endl;
				Que[rear++]=p;
				outputQue(front,rear);
			}

		}
		if(t == 0 && front!=rear)
		{
			p = Que[front++];
			cout<<now<<" "<<p.name<<"开始执行"<<endl;
			outputQue(front,rear);
		}
		now++;
		t++;
		p.RR_time++;
		Sleep(500);
	}
	output(rr);
}

void MFQ()
{
	int t=0;
	top = 0;
	int num;
	int front[10] ;
	int rear[10] ;
	memset(front,0,sizeof(front));
	memset(rear,0,sizeof(rear));
	int time[10]= {1,2,4,8,16};
	printf("请输入队列的个数(最多为5):");
	scanf("%d",&num);
	PCB p= {"0",0,0,0};
	int now = 0;
	int r=0;
	int index=0;
	t=0;
	while(1)
	{
		if(t == time[index])//时间片用完
			t=0;
		//扫描入队
		for(int i=r; i<5; i++)
		{
			if(pcb[i].arrive_time == now)   //此时间有进程到达
			{
				cout<<now<<" "<<pcb[i].name<<"到达"<<endl;
				MQ[0][rear[0]++]=pcb[i]; //入队
				outputMQ(num,front,rear);
				r=i+1;
			}
		}
		if(p.name!="0") //不是第一次
		{
			if(p.RR_time >= p.service_time)//如果已经完成服务
			{
				cout<<now<<" "<<p.name<<" "<<"结束!"<<endl;
				p.exit_time=now;
				t=0;
				mfq[top++]=p;
				if(top == 5)
					break;
				p.name="0";
			}
			else if(t == 0) //如果没有完成并且时间片用完了
			{
				cout<<now<<" "<<p.name<<" "<<"时间片用完!"<<endl;
				if(index+1<=num-1)
					MQ[index+1][rear[index+1]++]=p;
				else
					MQ[index][rear[index]++]=p;
				outputMQ(num,front,rear);
			}
		}
		if(t == 0)
		{
			int ff=0;
			for(int i=0; i<5; i++)
			{
				if(front[i]!=rear[i]) // 该级队列中有进程
				{
					ff=1;
					index=i;
					break;
				}
			}
			if(ff==1)
			{
				p = MQ[index][front[index]++];
				cout<<now<<" "<<p.name<<"开始执行"<<endl;
			}
			outputMQ(num,front,rear);
		}
		now++;
		t++;
		p.RR_time++;
		Sleep(500);
	}
	output(mfq);
}

int main()
{
	int n;
	init();

	while(1)
	{
		menu();
		scanf("%d",&n);
		switch(n)
		{
			case 1:
				input();
				break;
			case 2:
				display();
				break;
			case 3:
				FCFS();
				break;
			case 4:
				SJF();
				break;
			case 5:
				HRRN();
				break;
			case 6:
				RR();
				break;
			case 7:
				MFQ();
				break;
			case 8:
				outsum();
				break;
			case 0:
				exit(1);
				break;
			default :
				printf("请输入有效选项!\n");
		}
	}

}
1. 实验目的 调度的实质是操作系统按照某种预定的策略来分配资源。进程调度的目的是分配CPU资源。由于进程调度程序的频率很高,因此调度算法的好坏直接影响到操作系统的性能。本实验的目的是编程模拟实现几种常用的进程调度算法,通过对几组进程分别使用不同的调度算法,计算进程的平均周转时间和平均带权周转时间,比较各种算法的性能优劣。 2. 实验原理 [1]. 进程调度算法描述 进程调度算法包括先来先服务调度算法、最短作业时间优先(抢占式和非抢占式)、最高响应比调度算法4种。(每个人必须做FCFS,然后在后面的三种中任选种,即每个人必须做2种调度算法的模拟。) [2]. 衡量算法性能的参数 计算进程的平均周转时间和平均带权周转时间。 3. 实验内容 (1)编程实现本实验程序,要求: [1]. 建立进程进程控制块,进程控制块至少包括: a) 进程名称; b) 进程需要执时间; c) 进入就绪队列时间; d) 进程开始时间 e) 进程结束时间 [2]. 编程实现调度算法。 [3]. 进程及相关信息的输入。这些信息可以直接从键盘上输入,也可以从文件读取。 [4]. 时间片与时间流逝的模拟。本实验需要对算法的执计时,程序应该提供计算时间的方法。种最简单的方法是使用键盘,比如每敲次空格代表一个时间片的流逝。另种方法是使用系统时钟。 [5]. 进程序列执完毕,打印出结果信息。程序需要计算出每个进程的开始执时间、结束时间、周转时间和带权周转时间,并为整个进程序列计算平均周转时间和平均带权周转时间。程序将计算结果按定的格式显示在计算机屏幕上或输出到文件中。打印出进程调度顺序图。 [6]. 实现数据在磁盘文件上的存取功能。 (2)对下列就绪进程序列分别使用上面的几种算法调度,计算每种算法下的平均周转时间和平均带权周转时间。 进程号 到达时间 要求执时间 0 0 1 1 1 35 2 2 10 3 3 5 4 6 9 5 7 21 6 9 35 7 11 23 8 12 42 9 13 1 10 14 7 11 20 5 12 23 3 13 24 22 14 25 31
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值