ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

操作系统课程设计2 进程调度算法

2020-12-29 21:01:45  阅读:154  来源: 互联网

标签:课程设计 操作系统 int printf 进程 算法 time pcb HPF


进程调度算法的分析、设计与实现(110)

一、 本实验采用的调度算法设计理论描述(10分)

  1. FCFS(先来先服务):当在进程调度中采用该算法时,系统将按照进程到达的先后顺序来进行调度,或者说它是优先考虑在系统中等待时间最长的进程,而不管该进程所需执行的时间的长短,从后备队列中选择几个最先进入该队列的进程,将他们调入内存,为他们分配资源和创建进程,然后把它放入就绪队列。每次调度是从就绪的进程队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后,进程调度程序才将处理机分配给其他进程 。

  2. SPF(短进程优先):以进程的长短来计算优先级,进程越短其优先级越高。进程的长短是以进程所要求的运行时间来衡量的。SPF算法可以用于进程调度。把短进程优先调度算法用于进程调度时,它将从外存的进程后备队列中选择若干个估计运行时间最短的进程,优先将它们调入内存运行。

  3. RR(时间片轮转):系统根据FCFS策略,将所有的就绪进程排成一个就绪队列,并可设置每隔一定时间间隔即产生一次中断,激活系统中的进程调度顺序,完成一次调度,将CPU分配给队首进程,令其执行。当该进程的时间片耗尽或运行完毕时,系统再次将CPU分配给新的队首进程(或新到达的紧迫进程).由此,可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。

  4. HPF(优先级调度算法)
    非抢占式优先权调度算法
    系统一旦把处理机分配给优先权最高的进程后,便一直执行下去,至完成。

  5. 抢占式优先权调度算法
    只要系统中出现一个新的就绪进程,就进行优先权比较。若出现优先权更高的进程,则立即停止当前执行,并将处理机分配给新到的优先权最高的进程。

  6. HRRN(高响应比优先调度算法):高响应比优先调度算法的基本思想是把CPU分配给就绪队列中响应比最高的进程,既考虑作业的执行时间也考虑作业的等待时间,综合了先来先服务和最短作业优先两种算法的特点。
    该算法中的响应比是指作业等待时间与运行比值,响应比公式定义如下:
    响应比 =(等待时间+要求服务时间)/ 要求服务时间
    即:响应比计算:Ri = (Tw/Ts)+1 其中:Tw:等待时间;Ts:服务时间

二、数据结构模型及算法描述(必须画流程图)(15分)

1.PCB的定义(5分)
系统利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程,PCB中记录了操作系统所需要的、用于描述进程情况及控制进程运行所需要的全部信息,PCB是进程实体的一部分,是操作系统中最重要的记录型数据结构。
PCB的数据结构
struct pcb{ // 定义一个结构体,里面包含的有一个进程相关的信息
char name[10]; //进程名称
float arrivetime; //到达时间
float servicetime; //服务时间
float starttime; //开始时间
float finishtime; //结束时间
float zztime; //周转时间=finishtime-arrivetime
float dqzztime; //带权周转时间=zztime/servicetime
};
算法描述

  1. 先来先服务算法FCFS
    void FCFS(pcb *p,int N)
    按照作业进入系统的先后次序来挑选作业,先进入系统的作业优先被挑选

  2. 短作业优先SJF
    void sjff(pcb *p,int N)
    对短作业或者短进程优先调度的算法,将每个进程与其估计运行时间进行关 联选取估计计算时间最短的作业投入运行。

  3. 时间片轮转调度算法RR
    void RunProcess()
    每个进程被分配一个时间段,称作它的时间片,如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。

  4. 高优先级调度算法HPF
    void HPF()
    在优先级调度算法中,优先执行高优先级的进程。在算法实现中,默认数值大的表示优先级高

  5. 高响应比优先调度算法HRRN
    int hrrn(Node node,int t)
    计算进程响应比,选择高响应比的进程执行

    2.流程图(10分)
    先来先服务算法FCFS
    在这里插入图片描述

    短进程优先算法SPF
    在这里插入图片描述

时间片轮转算法RR
在这里插入图片描述

优先级调度算法HPF
在这里插入图片描述

高响应比优先算法HRRN

在这里插入图片描述

三、源代码(可以另附C源程序文件)(40分)

1) FCFS.cpp(实现先来先服务算法)

//先来先服务
#include <stdlib.h>
#include <stdio.h>
 
struct pcb{   // 定义一个结构体,里面包含的有一个进程相关的信息
	char name[10];        //进程名称 (输入)
	float arrivetime;     //到达时间 (输入)
	float servicetime;    //服务时间 (输入)
	float starttime;      //开始时间 
	float finishtime;     //结束时间 
	float zztime;        //周转时间=finishtime-arrivetime
	float dqzztime;      //带权周转时间=zztime/servicetime
};   
 
//输入进程信息
void input(pcb *p, int N)    //p为pdb数组名, N为pcb数组的元素个数 
{ 
	int i;   
    printf("\n"); 
	printf("请输入进程的名字  到达时间  服务时间:\n");
	for(i=0; i<=N-1; i++)    
	{    
		printf("请输入进程%d的信息:", i+1);  // i=0时,输入第1个进程相关信息 
		scanf("%s", &p[i].name);		
		scanf("%f", &p[i].arrivetime);		
		scanf("%f", &p[i].servicetime);
	}    
	
} 
   
//排序: 按照进程的arrivetime(从小到大)对pcb数组中的N个进程进行排序 
void sort(pcb *p, int N)   
{     
	for(int i=0; i < N-1; i++)
	{
		for(int j=i+1; j<N; j++)  
		{
			if(p[i].arrivetime > p[j].arrivetime)   
			{    
				pcb temp;    
				temp=p[i];    
				p[i]=p[j];    
				p[j]=temp;    
			}
		}
	}
} 
 
//运行
void run(pcb *p, int N)     
{
	int k;    
	for(k=0; k<=N-1; k++)    
	{    
		if(k==0) //第1个进程   
		{     
			p[k].starttime = p[k].arrivetime; //第1个进程到达之后即可执行   
			p[k].finishtime = p[k].starttime + p[k].servicetime; 
		}    
		else 
		{    
			p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime;    
			p[k].finishtime = p[k].starttime + p[k].servicetime;
		}    
	}    
	for(k=0; k<=N-1; k++)    
	{    
		p[k].zztime = p[k].finishtime - p[k].arrivetime;    
		p[k].dqzztime = p[k].zztime / p[k].servicetime;    
 
     }    
} 
  
//显示
void Print(pcb*p, int N)    
{
	int k;  
	printf("调用先来先服务算法以后进程运行的顺序是: ");
	printf("%s", p[0].name); //首先运行第一个进程p[0] 
	for(k=1; k<N; k++)    
	{
		printf("-->");		
		printf("%s", p[k].name); //输出 -->p[k].name 
	}   
	printf("\n"); 
	printf("具体进程调度信息:\n");
	printf("进程名  到达时间  服务时间  开始时间  结束时间  周转时间  带权周转时间\n");
	for(k=0; k<=N-1; k++)    
	{ 
		printf("%4s", p[k].name);
		printf("%10.0f", p[k].arrivetime);		
		printf("%10.0f", p[k].servicetime);		
		printf("%10.0f", p[k].starttime);		
		printf("%10.0f", p[k].finishtime);		
		printf("%10.3f", p[k].zztime);
		printf("%10.3f\n", p[k].dqzztime);		
     }      
}
 
//先来先服务算法FCFS
void FCFS(pcb *p,int N)    
{       
	sort(p,N);    
	run(p, N);    
	Print(p, N); 
	int k;
	float Attime = 0; //平均周转时间 
	float AQttime = 0; //平均带权周转时间 
	for(k=0; k<=N-1; k++)    
     {   
		Attime += p[k].zztime;  
		AQttime += p[k].dqzztime;		
     }  
	Attime = Attime / N; 
	AQttime = AQttime / N;
	printf("调用先来先服务算法的平均周转时间为:");
	printf("%.3f\n", Attime);
	printf("调用先来先服务算法的平均带权周转时间为:");
	printf("%.3f\n", AQttime);      
}  
 
int main( )
{
	pcb a[100]; //a为pcb数组   a[0]~a[N-1]对象第1个进程到第N个进程的信息 
	int N;      //N为进程数目 
	printf("\n");
	printf("\n"); 						
	printf("----------先来先服务调度算法----------");                           
	printf("\n");						
	printf("输入进程数目:");
	scanf("%d", &N);                            
	input(a, N); //a是pcb数组名,N是实际使用数组元素个数   
	FCFS(a, N); //fcfs模拟调度 
	return 0;	
}

2) SPF.cpp(实现短进程优先算法)

//短进程优先调度算法
#include <stdlib.h>
#include <stdio.h>
 
//定义一个结构体:PCB
struct pcb{   
char name[10];   
float arrivetime;   
float servicetime;   
float starttime;   
float finishtime;   
float zztime;   
float dqzztime;   
}; 
 
//***输入进程信息,将N个进程的信息写入pcb型数组***
void input(pcb *p,int N)   
{
	int i;   
	printf("\n"); 
	printf("请输入进程的名字  到达时间  服务时间: \n");
 
	for(i=0; i <= N-1; i++)   
	{   
		printf("请输入进程%d的信息:", i+1);
		scanf("%s", &p[i].name);	
		scanf("%f", &p[i].arrivetime);
		scanf("%f", &p[i].servicetime);	 
	}   
}
   
//***优先级排序***
void sort(pcb *p, int N)   
{   
	
	/*
	1、对pcb型数组中的元素进行一个简单的排序
	找到优先级最高的进程
	并把其他进程也进行简单排序,方便后续工作
	*/
	//排序: N次循环,每次找到从i到N-1中优先级最高的进程,放到p[i]
	for(int i=0;i<=N-1;i++)  
	{
		//循环比较剩余的变量    //排序后:从0~N-1  arrivetime增加 , arrivetime相同时, servicetime短的优先 
		for(int j=i+1;j<N;j++) 
		{
			if(p[i].arrivetime>p[j].arrivetime || (p[i].arrivetime==p[j].arrivetime && p[i].servicetime>p[j].servicetime) )   
			{  
				//p[j]的优先级高于p[i],因此把p[j]放到p[i]
				pcb temp;   
				temp = p[i];   
				p[i] = p[j];   
				p[j] = temp;   
             } 
		}
	}
	/*
	2、每个进程运行完成之后,找到当前时刻已经到达的最短进程
	P[0]优先级最高,p[0].finishtime=p[0].arrivetime+p[0].servicetime
	m!=0时:p[m].finishtime=p[m-1].finishtime+p[m].servicetime
	*/
	for(int m=0; m<N-1; m++)      
	{
		if(m == 0)   
			p[m].finishtime = p[m].arrivetime + p[m].servicetime;   
		else
			p[m].finishtime = ((p[m-1].finishtime >= p[m].arrivetime)? p[m-1].finishtime: p[m].arrivetime) + p[m].servicetime;
		//(1)找到p[m].finishtime时刻哪些进程已经到达
		int i=0;  //i统计 p[m].finishtime时刻有几个进程已经到达
		//从下一个进程p[m+1]开始寻找
		for(int n = m+1; n <= N-1; n++)   
		{
			if(p[n].arrivetime <= p[m].finishtime)              
				i++;   
			else
				break;
			    /*由于在第1步已经对进程按照到达时间进行了排序
			      故:当p[n].arrivetime > p[m].finishtime时,
				      说明p[n]进程和其后面的其他进程都未到达。
				i的值为p[m].finishtime时刻已经到达的进程数目。
			   */
		}  
		//(2)找到p[m].finishtime时刻已经到达的最短进程
		float min = p[m+1].servicetime;   //next进程服务时间为p[m+1].servicetime (初值) 
		int next = m+1;                   //next进程为m+1 (初值) 
		//p[m+1]至p[m+i]这i个已到达进程中找到最短进程
		for(int k = m+1; k < m+i; k++)       //k为m+1 ~ m+i-1   
		{   
			//min的初值是p[m+1].servicetime, k+1为m+2 ~m+i 
			if(p[k+1].servicetime < min)   
			{
				min = p[k+1].servicetime;              
				next = k+1;
			}                              
		}  
		//(3)把最短进程放在p[m+1]进程处
		pcb temp;               
		temp=p[m+1];              
		p[m+1]=p[next];              
		p[next]=temp;           
	}    
} 
  
//***运行***
void run(pcb *p, int N)   
{
	int k; 
	//计算各进程的开始时间和结束时间
	for(k=0; k <= N-1; k++)   
     {            
		if(k==0) //第1个进程   
		{     
			p[k].starttime = p[k].arrivetime; //第1个进程到达之后即可执行   
			p[k].finishtime = p[k].starttime + p[k].servicetime; 
		}    
		else 
		{    
			p[k].starttime = (p[k-1].finishtime >= p[k].arrivetime)? p[k-1].finishtime: p[k].arrivetime;    
			p[k].finishtime = p[k].starttime + p[k].servicetime;
		}    
	} 
	//计算各进程的周转时间和带权周转时间
	for(k=0; k<=N-1; k++)   
	{        
		p[k].zztime = p[k].finishtime - p[k].arrivetime;   
		p[k].dqzztime = p[k].zztime / p[k].servicetime;   
     }   
}  
 
//***显示***
void Print(pcb *p, int N)   
{
	int k;      
	printf("调用最短进程优先算法以后进程运行的顺序是: ");
	printf("%s",p[0].name); 
	for(k=1;k<N;k++)   
	{
		printf("-->");		
		printf("%s", p[k].name); 
	}    
	printf("\n"); 
	printf("具体进程调度信息:\n");
	printf("进程名  到达时间  服务时间  开始时间  结束时间  周转时间  带权周转时间\n");
	for(k=0; k<=N-1; k++)        
	{	
		printf("%4s", p[k].name);
		//%m.nf:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格
		printf("%10.0f", p[k].arrivetime);	
		printf("%10.0f", p[k].servicetime);
		printf("%10.0f", p[k].starttime);
		printf("%10.0f", p[k].finishtime);
		printf("%10.3f", p[k].zztime);
		printf("%10.3f\n", p[k].dqzztime);
	}         
}  
  
//***短进程优先***
void sjff(pcb *p,int N)   
{
	sort(p, N);                 
	run(p, N);         
	Print(p, N);  
	int k;
	float Attime = 0; // 平均周转时间 
	float AQttime = 0; //平均带权周转时间 
	for(k=0; k<=N-1; k++)    
     {   
		Attime += p[k].zztime;  
		AQttime += p[k].dqzztime;		
     }  
	Attime = Attime/N; 
	AQttime = AQttime/N;
	printf("调用短进程优先算法的平均周转时间为:");
	printf("%.3f\n", Attime);
	printf("调用短进程优先算法的平均带权周转时间为:");
	printf("%.3f\n", AQttime);      
}   
 
//***主函数***
int main()   
{ 
	//定义一个pcb型数组a
	pcb a[100]; 
	int N;  //进程数目                    		
	printf("\n");                          		
	printf("\n");		
	printf("---------------短进程优先调度算法--------------");	
	printf("\n");	
	printf("输入进程数目:");
	scanf("%d", &N);                 		
	input(a, N);  		
	sjff(a, N);
	return 0; 
}

3) RR.cpp(实现时间片轮转算法)

#include<stdio.h>
#include<stdlib.h>
#define MAX 10   //最大进程数
int Time;   //时间片
int process_amount;  //进程数量
int current_number = 0;   //当前执行的“号码牌”
int index = 0;       //就绪队列要发的“号码牌”,初始值为0
struct PCB
{
	char name[10];   //进程名字
	int arrivetime;   //到达时间
	int servicetime;   //服务时间
	int finishtime;   //完成时刻
	int sign_completion;  //标志是否完成调用,0表示没完成,1表示完成
	int remaining_time;  //剩余服务时间
	int number;          //进程在就绪队列里的“号码牌”
}process[MAX];

void input()     //初始化进程的信息
{
	int i;
	printf("请输入时间片:");
	scanf("%d",&Time);
	printf("\n请输入进程名称 到达时间 服务时间:\n");
	for(i = 0; i < process_amount; i ++)      
	{ 
		printf("请输入进程%d的信息:",i+1);
		scanf("%s%d%d",process[i].name,&process[i].arrivetime,&process[i].servicetime);
	
		process[i].remaining_time = process[i].servicetime;
		process[i].sign_completion = 0;
		process[i].number = 0;       //“号码牌”初始为0
	}
}

void BubbleSort()    //冒泡排序算法对进程抵达时间先后排序
{
	int i,j,n = process_amount;
    for(i = 0; i < n - 1; i++)         
    for(j = 0; j < n - 1 - i; j++) 
	{
		if(process[j].arrivetime > process[j+1].arrivetime)
		{
			process[n] = process[j+1];
			process[j+1] = process[j];
			process[j] = process[n];

		}
	}
}

void RunProcess()     //时间片轮转调用过程
{
	int time = process[0].arrivetime;      //给当前时间赋初值 
	int sum = 0;					//记录完成的进程数 
	int i,j;
    while(sum < process_amount)
    {  
	for(i = 0;  i < process_amount; i++)
		if(current_number == process[i].number && process[i].sign_completion == 0)
		{
		 	if(process[i].remaining_time <= Time)    //剩余服务时间少于等于一个时间片 
		 	{
		 	time = time + process[i].remaining_time;
		 	process[i].sign_completion = 1;
		 	process[i].finishtime = time;
		 	process[i].remaining_time = 0;
			printf("%s ",process[i].name);          
			sum++;
			current_number++;
			for(j = i + 1; j < process_amount; j++)     //检测后面有没有新进程到达
				if(process[j].arrivetime <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
		 	}
		 	
		 	else if(process[i].remaining_time > Time)//剩余服务时间大于一个时间片 
		 	{
		 		time = time + Time;
				process[i].remaining_time -= Time;
				printf("%s ",process[i].name);
				current_number++;
				for(j = i + 1; j < process_amount; j++)    //检测后面有没有新进程到达
				if(process[j].arrivetime <= time && process[j].number == 0)
				{
					index++;
					process[j].number = index;
				}
				index++;
				process[i].number = index;
			} 
		}
	if(index < current_number && sum < process_amount)   // 还有没执行的进程,且没进入就绪队列 
	{
	for(i = 0; i <= process_amount; i++)
		if(process[i].sign_completion == 0) 
		{
			time = process[i].arrivetime;
			index++;
			process[i].number = index;
			break;
		}
	}
}
}

void output()   //打印信息
{
	int i;
	 float daiquan=0,zhouzhuan=0;

	printf("程序名 到达时间 服务时间 完成时间 周转时间  带权周转时间\n");
	for(i = 0; i < process_amount; i++)
	{
		float weight_time = (float)(process[i].finishtime - process[i].arrivetime)/process[i].servicetime;

		printf("  %s\t  %d\t   %d\t    %d\t     %d\t\t%.2f\n",process[i].name,process[i].arrivetime,process[i].servicetime,
			process[i].finishtime,process[i].finishtime-process[i].arrivetime,weight_time);	
		zhouzhuan+=(process[i].finishtime-process[i].arrivetime);
		daiquan+=weight_time;
	}
	printf("调用时间片轮转算法的平均周转时间为:");
	printf("%.2f\n", zhouzhuan/ process_amount);
	printf("调用时间片轮转算法的平均带权周转时间为:");
	printf("%.2f\n",daiquan/ process_amount);
}

int main()
{
	
	printf("\n-------------时间片轮转法调度算法------------\n");
	printf("请输入总进程数:");
	scanf("%d",&process_amount);
	input();
	BubbleSort();
	printf("调用时间片轮转算法后进程运行顺序是:\n");
	RunProcess();
	printf("\n");
	output();
	
	printf("\n");
	return 0;
}

4) HPF.cpp(实现优先级调度算法)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<queue>
#include<cstdlib>
#include<iomanip>
#include<algorithm>
using namespace std;
#define N 20                            //进程数
#define WFA wait_for_arrival            //进程还未到——所有非零时刻到达的进程执行前的初始状态
#define Ready ready_state               //进程到达后处于就绪状态,等待CPU资源
#define Running running_state           //进程处于运行态
#define Finish end_of_execution         //进程执行结束
///数据结构——通用的进程控制块PCB
struct PCB
{
    char process_name;                  //进程名
    double arrival_time;                //进程到达时间
    double service_time;                //进程要求服务时间
    double start_time;                  //进程开始执行时间
    double need_service_time;           //进程还需占用CPU时间
    double end_time;                    //进程执行完成时间
    double process_priority;            //进程优先级
    double turnaround_time;             //进程周转时间
    double weight_turnaround_time;      //进程带权周转时间
    string status;                      //进程状态
};

PCB pcb[N];                             //每个进程维护一个进程控制块
vector<PCB> pcbList;                    //pcbList向量
queue<PCB>Ready;                        //就绪队列
double average_TT;                      //平均周转时间
double average_WTT;                     //平均带权周转时间
int n;                                  //进程数
int flag = 0;

///函数定义:
void Init_process();                     //进程初始化
bool cmp_name(PCB a, PCB b);             //按进程名排序,按序输出
bool cmp_process_priority(PCB a, PCB b); //按优先级大小排序

void HPF();                              //HPF优先级调度算法
void Result_Print(PCB Tmp_pcb[]);        //最终结果打印(各进程的完成时间,各进程的周转时间及带权周转时间)
bool All_finished(PCB pd_pcb[]);         //判断是不是所有进程都已经执行结束,作为循环的判断条件(状态输出的时间优化)

/************************************
主函数:main()
*************************************/
int main()
{
    Init_process();    //进程初始化
	 HPF();
    return 0;
}

/************************************
函数名称:Init_process()
函数功能:进程初始化
返回值:无
*************************************/
void Init_process()
{
	int i;
	cout<<endl<<"---------------高优先级调度算法--------------"<<endl;
    cout<<"请输入进程数:";
    cin>>n;
    cout<<"请依次输入 进程名 到达时间 服务时间(如:A 0 3)"<<endl;
    for( i = 0; i < n; i++)
    {
        char p_name;             //进程名
        double p_arrive,p_service; //进程到达时间 服务时间
        cin>>p_name>>p_arrive>>p_service;
        pcb[i].process_name = p_name;
        pcb[i].arrival_time = p_arrive;
        pcb[i].service_time = p_service;
        if(!p_arrive) pcb[i].status = "Ready";
        else pcb[i].status = "WFA";
    }
}

/************************************
函数名称:cmp_name(PCB a, PCB b)
函数功能:按进程名排序,按序输出
返回值:无
*************************************/
bool cmp_name(PCB a, PCB b)
{
    return a.process_name < b.process_name;
}

/************************************
函数名称:Print(PCB Tmp_pcb[])
函数功能:格式化输出
返回值:无
*************************************/
void Result_Print(PCB Tmp_pcb[])
{
    PCB cp_pcb[N];
	int i;
    for( i=0; i < n; i++)
        cp_pcb[i] = Tmp_pcb[i];
    sort(cp_pcb,cp_pcb+n,cmp_name);
    /*for( i = 0; i < 100; i++) cout<<"*";*/
    cout<<endl;
    cout<<setw(3)<<" "<<"进程名"<<setw(14)<<"到达时间"<<setw(13)<<"服务时间"<<setw(12)<<"完成时间"<<setw(12)<<"周转时间"<<setw(20)<<"带权周转时间"<<"\t  "<<endl;
   
    for( i = 0; i < n; i++)
    {
        cout<<setw(6)<<cp_pcb[i].process_name<<setw(14)<<cp_pcb[i].arrival_time<<setw(12)<<cp_pcb[i].service_time
        <<setw(12)<<cp_pcb[i].end_time<<setw(12)
        <<cp_pcb[i].turnaround_time<<setw(4)<<" "<<"\t\t"<<cp_pcb[i].weight_turnaround_time<<setw(8)<<"\t"<<" "<<" "<<" ";
     cout<<" "<<endl;
    }
   /* for( i = 0; i < 100; i++) cout<<"*";*/
    cout<<endl;
}

/************************************
函数名称:bool All_finished(PCB pd_pcb[]);
函数功能:判断是不是所有进程都已经
执行结束,作为循环的判断条件(状态
输出的时间优化)
返回值:true or false
*************************************/
bool All_finished(PCB pd_pcb[])
{
    int t=0,i;
    for( i = 0; i < n; i++)
    {
        if(pd_pcb[i].status == "Finish")
            t++;   //继续循环执行
    }
    if(t==n)  return false;
    else return true;
}

/************************************
函数名称:cmp_process_priority(PCB a, PCB b)
函数功能:按优先级大小排序
(注:优先级数值越大,优先级越高)
返回值:无
*************************************/
bool cmp_process_priority(PCB a, PCB b)
{
    if(a.arrival_time != b.arrival_time)
        return a.process_priority > b.process_priority;
    else return a.arrival_time < b.arrival_time;
}

/************************************
函数名称:HPF()
函数功能:HPF优先级调度算法
返回值:无
*************************************/
void HPF()
{
    PCB HPF_pcb[N];
    PCB Res_PCB[N];
    int t = 0;
	int i,j,m,k;
    for( i = 0; i < n; i++)
        HPF_pcb[i] = pcb[i];
    cout<<"请您依次输入代表进程{";
    for( i = 0; i < n-1; i++)
        cout<<HPF_pcb[i].process_name<<" ";
    cout<<HPF_pcb[n-1].process_name<<"}的优先级的数值:"<<endl;
    for( i = 0; i < n; i++)
        cin>>HPF_pcb[i].process_priority;
    sort(HPF_pcb,HPF_pcb+n,cmp_process_priority);                 //按优先级大小排序
    //for(int i = 0; i < n; i++)
    //    cout<<HPF_pcb[i].process_name << " "<<HPF_pcb[i].arrival_time<<" "<<HPF_pcb[i].service_time<<" "<<HPF_pcb[i].process_priority<<endl;
    cout<<endl;
    int excute_time = HPF_pcb[0].arrival_time;
    flag = 0;
    for( i = 0; i < n; i++)                                    //找 所有进程中 最早到达的进程时间 即为 系统的初始时间
    {
        excute_time = excute_time > HPF_pcb[i].arrival_time ? HPF_pcb[i].arrival_time : excute_time;
    }
    for(; All_finished(HPF_pcb); excute_time++)               //按总时间遍历 输出中间状态
    {
        for ( i = 0; i < n; i++)                               //遍历进程
        {
            if(HPF_pcb[i].arrival_time == excute_time && !flag)   //先到的进程若CPU空闲则先执行,就绪队列中有其他进程排队时,选择优先级高的进程
            {
                for( j = 0; j < n; j++)                        //同时间到达的,均修改状态
                {
                    if(HPF_pcb[j].arrival_time <= excute_time && HPF_pcb[j].status == "WFA")
                        HPF_pcb[j].status = "Ready";
                }
                for( j = 0; j <= i; j++)                                          //同时间到达的,先选优先级高的
                {
                    if(HPF_pcb[j].status == "Ready")
                    {
                        HPF_pcb[j].start_time = excute_time;                          //当前CPU空闲,到达的进程执行
                        HPF_pcb[j].end_time = excute_time + HPF_pcb[j].service_time;  //非抢占式,故该进程结束时间= 当前时间 + 服务时间
                        HPF_pcb[j].need_service_time = HPF_pcb[j].service_time;       //仍需要占用CPU的时间
                        HPF_pcb[j].status = "Running";                                //修改当前进程的状态为Running
                        Res_PCB[t++] = HPF_pcb[j];
                        flag = 1;
                        break;
                    }
                }
                break;
            }
            else if(HPF_pcb[i].arrival_time == excute_time && flag && HPF_pcb[i].status == "WFA")   //某进程结束,当前进程到达
            {
                bool mark = 0;
                HPF_pcb[i].status = "Ready";                //某进程到达,但CPU被占用着,该状态为Ready
                for( j = 0; j < n; j++)
                {
                    if(HPF_pcb[j].status == "Running" && HPF_pcb[j].end_time == excute_time)    //找到正在执行的进程,有且只有一个,这个进程刚好结束
                    {
                        HPF_pcb[j].status = "Finish";       //某进程执行完毕
                        flag = 0;
                        HPF_pcb[j].need_service_time = 0;   //不再需要CPU资源
                        HPF_pcb[j].turnaround_time = excute_time - HPF_pcb[j].arrival_time;     //周转时间 = 当前时间 - 到达时间
                        HPF_pcb[j].weight_turnaround_time = 1.0 * (HPF_pcb[j].turnaround_time)/(HPF_pcb[j].service_time);   //带权周转时间 = 周转时间 / 服务时间
                        HPF_pcb[j].weight_turnaround_time = ((int)((HPF_pcb[j].weight_turnaround_time*1000) + 0.5)) * 1.0 / 1000;
                        for(m = i; m < n; m++)         //若有其他进程也在当前时刻到达,状态位需进行修改
                        {
                            if(HPF_pcb[m].arrival_time <= HPF_pcb[j].end_time && HPF_pcb[j].status == "WFA")
                            {
                                HPF_pcb[m].status = "Ready";
                            }
                        }
                        for(k = 0; k < n; k++)                                             //找第一个ready进程
                        {
                            if(HPF_pcb[k].status == "Ready")
                            {
                                flag = 1;
                                HPF_pcb[k].start_time = excute_time;                           //开始时间等于当前时间
                                HPF_pcb[k].end_time = excute_time + HPF_pcb[k].service_time;   //进程的结束时间 = 当前时间 + 服务时间
                                HPF_pcb[k].status = "Running";                                 //修改进程状态 为 Running
                                Res_PCB[t++] = HPF_pcb[k];
                                HPF_pcb[k].need_service_time = HPF_pcb[k].service_time;
                                break;
                            }
                        }
                        mark = 1;
                    }
                    else if(HPF_pcb[j].status == "Running" && HPF_pcb[j].end_time!=excute_time) //找到正在执行的进程,有且只有一个,正在执行
                    {
                        HPF_pcb[j].need_service_time = HPF_pcb[j].end_time - excute_time;       //结束时间 - 当前时间 = 进程仍需CPU时间
                        mark = 1;
                        for(int m = i; m < n; m++)
                        {
                            if(HPF_pcb[m].arrival_time <= excute_time && HPF_pcb[m].status == "WFA")
                            {
                                HPF_pcb[m].status = "Ready";
                            }
                        }
                    }
                    if(mark) break;
                }
                break;
            }
            else if(HPF_pcb[i].end_time == excute_time && HPF_pcb[i].status == "Running")   //某进程执行结束
            {
                HPF_pcb[i].status = "Finish";        //某进程执行完毕
                flag = 0;
                HPF_pcb[i].need_service_time = 0;    //不再需要CPU资源
                HPF_pcb[i].turnaround_time = excute_time - HPF_pcb[i].arrival_time;
                //周转时间 = 当前时间 - 到达时间
                HPF_pcb[i].weight_turnaround_time = 1.0 * (HPF_pcb[i].turnaround_time)/(HPF_pcb[i].service_time);
                //带权周转时间 = 周转时间 / 服务时间
                HPF_pcb[i].weight_turnaround_time = ((int)((HPF_pcb[i].weight_turnaround_time*1000) + 0.5)) * 1.0 / 1000;
                //保留两位小数——四舍五入
                for(j = i; j < n; j++)           //如果当前进程执行结束时,下一进程刚好到达,状态位需进行修改
                {
                    if(HPF_pcb[j].arrival_time == HPF_pcb[i].end_time && HPF_pcb[j].status == "WFA")
                    {
                        HPF_pcb[j].status = "Ready";
                    }
                }
                for( j = 0; j < n; j++)                                             //找第一个ready进程
                {
                    if(HPF_pcb[j].status == "Ready")
                    {
                        flag = 1;
                        HPF_pcb[j].start_time = excute_time;                           //开始时间等于当前时间
                        HPF_pcb[j].end_time = excute_time + HPF_pcb[j].service_time;   //进程的结束时间 = 当前时间 + 服务时间
                        HPF_pcb[j].status = "Running";                                 //修改进程状态 为 Running
                        Res_PCB[t++] = HPF_pcb[j];
                        HPF_pcb[j].need_service_time = HPF_pcb[j].service_time;
                        break;
                    }
                }
                break;
            }
        }
    }

   
    Result_Print(HPF_pcb);
    average_TT = 0;
    average_WTT = 0;
    for(i = 0; i < n; i++)
    {
        average_TT += HPF_pcb[i].turnaround_time;
        average_WTT += HPF_pcb[i].weight_turnaround_time;
    }
    cout<<"调用优先级算法的平均周转时间为:";
    cout<<average_TT/n<<endl;
    cout<<"调用优先级算法的平均带权周转时间为:";
    cout<<average_WTT/n<<endl<<endl;
}

5) HRRN.cpp(实现高响应比优先算法)

 #include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
	char name[10];
	int into;
	int runtime;
	int start;
	int finish;
	int status;
	int hrrn;
	int sum;
}Node;


int select(Node node[],int n)
{
	int i,flag=0;
	for(i=0;i<n;i++)
	{
		if(node[i].status==0)
		{
		flag=1;
		break;
		}
	}
	if(1==flag)
		return i;
	else
		return -1;
}


int hrrn(Node node,int t)
{
	return (node.runtime+t-node.into)/node.runtime;
}

int main()
{
	int n,i,j,max,t=0;
	Node node[100];
	printf("\n------------高响应比优先调度算法-------------\n");
	printf("输入进程数:");
	scanf("%d",&n);
	getchar();
	printf("进程名称 到达时间 服务时间\n");
	for(i=0;i<n;i++)
	{
	scanf("%s",node[i].name);
	scanf("%d",&node[i].into);
	scanf("%d",&node[i].runtime);
	getchar();
	node[i].status=0;
	if(0==i)
	node[i].hrrn=0;
	}

	while(1)
	{
			int index;
			index=select(node,n);
			int flag=0;
			if(index==-1)
				break;
			max=0;
			for(i=0;i<n;i++)
			{
				if(node[i].into<=t&&0==node[i].status)
				{
					node[i].hrrn=hrrn(node[i],t);
					if(0==i)
						node[i].hrrn=0;
					if(node[i].hrrn>node[max].hrrn)
						max=i;
					flag=1;
				}
			}

		if(1==flag)
		{
			node[max].start=t;
			t+=node[max].runtime;
			node[max].status=1;
			node[max].finish=t;
			node[max].sum=node[max].finish-node[max].into;
		}
		else{
			t++;
		}
	}
	for(i=0;i<n-1;i++)
	{
		for(j=i;j<n-1;j++)
		{
			if(node[i].finish>node[j+1].finish)
			{
				Node temp=node[i];
				node[j]=node[j+1];
				node[j+1]=temp;
			}
		}
	}
	printf("   进程名称 到达时间 服务时间 开始时间 结束时间 周转时间 带权周转时间\n");
	float sum=0,sum2=0;
	for(i=0;i<n;i++)
	{
		float daiquan=0;
		int zhouzhuan=0;
		zhouzhuan =node[i].finish-node[i].into;
		daiquan=(float)zhouzhuan/node[i].runtime;
		printf("\t%s\t %d\t %d\t %d\t %d\t %d\t %.2f\n",node[i].name,node[i].into,
			node[i].runtime,node[i].start,node[i].finish,zhouzhuan,daiquan);
		sum+=zhouzhuan;
		sum2+=daiquan;
	}
	printf("调用HRRN算法的平均周转时间为:%.2f\n",sum/n);
	printf("调用HRRN算法的平均带权周转时间为:%.3f\n",sum2/n);
	return 0;
}

四、程序运行结果及分析(35分)

进程的各种数据,见下表

在这里插入图片描述

 FCFS算法
---------------------------------------------运行结果-------------------------------------------
在这里插入图片描述
--------------------------------------------结果分析-----------------------------------------------
系统将按照进程到达的先后顺序来进行调度,首先进程A被调度,直到进程A执行完后,进程B才被调度,因此进程的调度顺序依次是A-B-C-D-E
周转时间=完成时间-到达时间
带权周转时间=周转时间/服务时间

 短进程优先算法
---------------------------------------------运行结果--------------------------------------------
在这里插入图片描述

-------------------------------------------结果分析-----------------------------------------------
以进程的长短来计算优先级,进程越短其优先级越高,进程A先到达,被进行调度,当进程A执行完时,就绪队列中只有B到达,因此进程B进行调度。当B调度完时,进程C、D、E均在就绪队列中,由于E的进程短,所以优先被调度,因此进程的执行顺序是A-B-E-C-D

 RR时间片轮转算法
---------------------------------------------运行结果--------------------------------------------
在这里插入图片描述
---------------------------------------------结果分析--------------------------------------------
就绪队列表
在这里插入图片描述
由表可知,进程的调度顺序依次是A-A-B-A-B-C-B-D-C-B-E-D-C-B-E-D-C-B-D-D
 HPF高优先级调度算法
在这里插入图片描述
--------------------------------------------运行结果------------------------------------------

在这里插入图片描述

-------------------------------------------结果分析--------------------------------------------
通过优先级的大小决定进程调度的顺序,进程A先到达并执行至单位时间11,此时BCDE进程全部到达,根据优先级最大最先执行的约定,接下来执行的顺序依次是:B(5)—E(4)—C(2)—D(1)
 HRRN高响应比优先调度算法
-------------------------------------------运行结果--------------------------------------------
在这里插入图片描述

-------------------------------------------结果分析--------------------------------------------
把CPU分配给就绪队列中响应比最高的进程,T=0时,A执行,T=3时A结束B执行,T=9时,B结束CDE到达,T=13时,C结束DE到达,T=15时,E结束,T=20时,D结束。

五、课程设计心得与体会(5分,有即可给分)

通过本次实验,我们深刻的理解了操作系统中作业资源的分配方式和作业的调度方式及相关的算法。通过实际的上机操作对所学知识进行了巩固,除了更深入的了解进程调度算法,还对数据结构进行了复习,让我们受益匪浅。
同时,在这次上机中我们也遇到了一些问题:

  1. PCB结构体声明不当
  2. 循环使用不当
  3. 循环变量未进行初始化,导致输出溢出
  4. 输出用户体验不佳
    对此,我们上网查资料,查阅不同的参考书,最终把问题给解决了。总的来说,操作系统实验重在理解每一个算法的意图和目的,那么就选择适当的数据结构模拟过程就可以完成相关算法了,本次OS课程设计是对我们专业知识和实践能力的一大考验,使我们积累了不少经验,为以后的专业学习打下了坚实的基础。

六、参考文献:(5分,有即可给分)

[1]汤小丹等. 计算机操作系统(第四版). 西安:西安电子科技大学出版社2014
[2]汤子瀛等. 计算机操作系统(修订版). 西安:西安电子科技大学出版社2000
[3]zh13487.几种常见的调度算法https://blog.csdn.net/zh13487/article/details/83928284
[4]征途黯然. 操作系统 作业调度实验报告https://blog.csdn.net/qq_43592352/article/details/106849617

标签:课程设计,操作系统,int,printf,进程,算法,time,pcb,HPF
来源: https://blog.csdn.net/weixin_44567763/article/details/111936617

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有