操作系统原理与实验——实验三优先级进程调度

news2024/11/15 14:19:44

实验指南

运行环境:

Dev c++

算法思想: 

本实验是模拟进程调度中的优先级算法,在先来先服务算法的基础上,只需对就绪队列到达时间进行一次排序。第一个到达的进程首先进入CPU,将其从就绪队列中出队后。若此后队首的进程的到达时间大于上一个进程的完成时间,则该进程进入CPU,其开始时间即到达时间;否则如果上一个进程完成后,已经有多个进程到达,则需从已到达的进程中寻找到优先级最高的进程,并将其取出,进入CPU执行。直到所有进程执行完毕。

核心数据结构:

typedef struct data{

      int hour;

      int minute;

}time;

typedef struct node{

     

      int id;//进程编号

      char name[20];//进程名

      int good;//优先级

      time arrive;//到达就绪队列的时间

      int zx;//执行时间

      time start;//开始执行时间

      time finish;//执行完成时间

      int zz;//周转时间=执行完成时间-到达就绪队列时间

      float zzxs;//带权周转时间=周转时间/执行时间

      struct node* next;

     

}Node;

typedef struct Queue{

     

      Node* front = NULL;

      Node* tail = NULL;

     

}Queue;

程序主体框架:

#include <iostream>

#include <stdio.h>

#include <malloc.h>

#include <string.h>

using namespace std;

typedef struct data{

    int hour;

    int minute;

}time;

typedef struct node{

   

    int id;//进程编号

    char name[20];//进程名

    int good;//优先级

    time arrive;//到达就绪队列的时间

    int zx;//执行时间

    time start;//开始执行时间

    time finish;//执行完成时间

    int zz;//周转时间=执行完成时间-到达就绪队列时间

    float zzxs;//带权周转时间=周转时间/执行时间

    struct node* next;

   

}Node;

typedef struct Queue{

   

    Node* front = NULL;

    Node* tail = NULL;

   

}Queue;

Queue* init(){

   

    Queue* p = (Queue*)malloc(sizeof(Queue));

    p->front = NULL;

    p->tail = NULL;

    return p;

   

}

//函数名:timecompare()          参数:tt 当前时间, p 进程到达时间

bool timecompare(time tt,time p){//tt<p(时间没到) false    tt >= p true

    //函数功能:比较进程到达时间和当前时间,若小于则返回false,否则返回true

   

}

//函数名:timecompare2()          参数:tt 当前时间, p 进程到达时间

bool timecompare2(time tt,time p){//tt<=p(时间没到) false    tt > p true

    //函数功能:比较进程到达时间和当前时间,若小于等于则返回false,否则返回true

   

}

//函数名:Levelcompare()          参数:p,q 进程

bool Levelcompare(Node* p,Node* q){

    //函数功能:比较p,q的优先级,p的优先级高则返回true,低则返回false,否则比较到达时间,p先或同时到达则返回true,反之则false

   

}

//函数名:LevelSorted()          参数:que 进程队列指针

void LevelSorted(Queue* que){

//函数功能:对进程队列按优先级排序

   

}

//函数名:ComputeTime()    参数:tt 当前时间的指针,q 当前进程的指针

time ComputeTime(time* tt,Node* q){

   

//函数功能:更新当前时间和进程的各项时间

          

}

//函数名:priority()    参数:que进程队列指针,tt当前时间 n 进程数

Queue* priority(Queue *que,time tt,int n){

   

//函数功能:进行优先级进程调度,并同时更新当前时间。

   

}

//函数名:Print()    参数:que进程队列指针, n 进程数

void Print(Queue* que,int n){

    //函数功能:打印输出进程优先进程调度结果

   

}

//函数名:ScanIn()    参数:wait进程队列指针, n 进程数

time ScanIn(Queue* wait,int n){

   

    //函数功能:输入进程信息,返回最早的进程到达时间

          

}

int main(){

   

    Queue* wait;

    wait = init();

    int flag,n;

    time earlytime;

   

    while(1){

       printf("请输入操作:(1:开始进程;0:结束进程):");

       scanf("%d",&flag);

       if(flag == 0){

           printf("\n操作结束!\n");

           break;

       }

       else{

           printf("请输入进程数量:");

           scanf("%d",&n);

           earlytime = ScanIn(wait,n);

          

           LevelSorted(wait);

           wait = priority(wait,earlytime,n);

           Print(wait,n);

           wait = init();

          

       }

    }

   

    return 0;

}

    

测试数据

/*

1001 p1 1 9:40 20
1004 p4 4 10:10 10
1005 p5 3 10:05 30
1002 p2 3 9:55 15
1003 p3 2 9:45 25

*/

/*

5001 p1 1 14:40 20
5002 p4 2 10:10 10
5003 p5 3 10:05 30
5004 p2 4 9:55 15
5005 p3 5 9:45 25
5006 p6 6 10:40 20
5007 p8 7 11:10 10 
5008 p9 8 12:05 30
5009 p10 9 13:55 15
5010 p7 10 7:15 15

*/

关键代码

#include <iostream>
#include <stdio.h>
#include <malloc.h>
#include <string.h>
using namespace std;

typedef struct data{
	int hour;
	int minute;
}time;

typedef struct node{
	
	int id;//进程编号 
	char name[20];//进程名 
	int good;//优先级 
	time arrive;//到达就绪队列的时间 
	int zx;//执行时间 
	time start;//开始执行时间 
	time finish;//执行完成时间 
	int zz;//周转时间=执行完成时间-到达就绪队列时间 
	float zzxs;//带权周转时间=周转时间/执行时间 
	struct node* next;
	
}Node;

typedef struct Queue{
	
	Node* front = NULL;
	Node* tail = NULL;
	
}Queue;
void Print(Queue* que,int n);
Queue* init(){
	
	Queue* p = (Queue*)malloc(sizeof(Queue));
	p->front = NULL;
	p->tail = NULL;
	return p;
	
} 
//函数名:timecompare()          参数:tt 当前时间, p 进程到达时间
bool timecompare(time tt,time p){//tt<p(时间没到) false    tt >= p true 
	//函数功能:比较进程到达时间和当前时间,若小于则返回false,否则返回true 
	if((tt.hour<p.hour)||((tt.hour==p.hour)&&(tt.minute<p.minute)))
	return false;
	else
	return true;
}
//函数名:timecompare2()          参数:tt 当前时间, p 进程到达时间
bool timecompare2(time tt,time p){//tt<=p(时间没到) false    tt > p true 
	//函数功能:比较进程到达时间和当前时间,若小于等于则返回false,否则返回true
	if((tt.hour<p.hour)||((tt.hour==p.hour)&&(tt.minute<p.minute||tt.minute==p.minute)))
	return false;
	else
	return true;
}
//函数名:Levelcompare()          参数:p,q 进程
bool Levelcompare(Node* p,Node* q){
	//函数功能:比较p,q的优先级,p的优先级高则返回true,低则返回false,否则比较到达时间,p先或同时到达则返回true,反之则false
	if(p->good>q->good)
	return true;
	else if(p->good<q->good)
	return false;
	else
	{
		if((p->arrive.hour<q->arrive.hour)||(p->arrive.hour==q->arrive.hour&&p->arrive.minute<=q->arrive.minute))
		return true;
		else
		return false;
	}

}
//函数名:LevelSorted()          参数:que 进程队列指针
void LevelSorted(Queue* que){
	
//函数功能:对进程队列按优先级排序	
	Node *bl,*head=NULL,*pre=NULL,*q=NULL,*p,*c;
	bl=que->front;
	while(bl!=NULL)
	{
		Node *p=(Node *)malloc(sizeof(Node));
	 	
	 	*p=*bl;//重点:指针的应用 
		p->next=NULL;
	 	if(head==NULL)
	 	{
	 		head=p;
	 		q=p;
		}
		else
		{
			q=head;
			pre=NULL;
			while(q!=NULL)
			{
				
				if(Levelcompare(p,head))
				{
					p->next=head;
					head=p;
					q=head;
					break;
				}
				else if(!Levelcompare(p,q)&&q->next==NULL)
				{
					q->next=p;
					break;
				}
				else if(Levelcompare(p,q))
				{
					p->next=q;
					pre->next=p;
					break;
				}
				pre=q;
				q=q->next;
				
			}
			
		}
		bl=bl->next;
	}
	que->front=head;
	que->tail=pre;
	
}

//函数名:ComputeTime()    参数:tt 当前时间的指针,q 当前进程的指针
time ComputeTime(time* tt,Node* q){
	
//函数功能:更新当前时间和进程的各项时间
	q->start.hour=tt->hour;
	q->start.minute=tt->minute;
	q->finish.minute=(q->start.minute+q->zx)%60;
	q->finish.hour=q->start.hour+(q->start.minute+q->zx)/60;
	q->zz=q->finish.hour*60+q->finish.minute-q->arrive.hour*60-q->arrive.minute;
	q->zzxs=q->zz*1.0/q->zx;
	tt->hour=q->finish.hour;
	tt->minute=q->finish.minute;
			
}
//函数名:priority()    参数:que进程队列指针,tt当前时间 n 进程数
Queue* priority(Queue *que,time tt,int n){
	
//函数功能:进行优先级进程调度,并同时更新当前时间。
int count=n;
	Node *pre=NULL,*p=NULL,*head=NULL,*q=NULL,*Head;
	Head=que->front;
	p=Head;
	while(1)
	{
		if((p->arrive.hour==tt.hour)&&(p->arrive.minute==tt.minute))
		{
			break;
		}pre=p;
			p=p->next;
	}	
	Node *N=(Node *)malloc(sizeof(Node));
	*N=*p;
	N->next=NULL;
	head=N;
	q=head;
	if(p==Head)
	{
		Head=Head->next;
		free(p);
		count--;
	}
	else
	{
		pre->next=p->next;
		free(p);
		count--;
	}
	ComputeTime(&tt,N);
	while(count)
	{
		p=Head;
		pre=NULL;
		while(p!=NULL)
		{
			if(timecompare2(tt,p->arrive)==true)//提前到达 
			{
				Node *N=(Node *)malloc(sizeof(Node));
				*N=*p;
				N->next=NULL;
				q->next=N;
				q=q->next;
				if(p==Head)
				{
					Head=Head->next;
					free(p);
					count--;
				}
				else
				{
					pre->next=p->next;
					free(p);
					count--;
				}
				ComputeTime(&tt,N);
				break;
			}
			pre=p;
			p=p->next;
		}
		if(p==NULL)//按到达时间先后 
		{
			Node *l,*r;
			l=Head;
			r=Head;
			while(r!=NULL)
			{
				if(timecompare2(l->arrive,r->arrive))
				{
					l=r;
				}
				r=r->next;
			}//找到最小到达时间 
			
		tt.hour=l->arrive.hour;tt.minute=l->arrive.minute;
				Node *N=(Node *)malloc(sizeof(Node));
				*N=*l;
				N->next=NULL;
				q->next=N;
				q=q->next;pre=Head;
				if(l==Head)
				{
					Head=Head->next;
					free(l);
					count--;
				}
				else
				{
					while(pre->next!=l)
					{
						pre=pre->next;
					}
					pre->next=l->next;
					free(l);
					count--;
				}
				ComputeTime(&tt,N);
		}
	}
	
			que->front=head;
			return que;
}
//函数名:Print()    参数:que进程队列指针, n 进程数
void Print(Queue* que,int n){
	//函数功能:打印输出进程优先进程调度结果
	float pz=0,px=0;
	Node *p;
	p=que->front;
	printf("模拟进程优先进程调度过程输出结果\n  id号    名字\t优先级\t到达时间  执行时间(分钟)\t开始时间\t完成时间  周转时间(分钟)  带权周转系数\n"); 
	while(p!=NULL)
	{
		printf("%6d %6s %6d %6d:%02d %10d %17d:%02d %12d:%02d %10d(分钟) %12.2f\n",p->id,p->name,p->good,p->arrive.hour,p->arrive.minute,p->zx,p->start.hour,p->start.minute,p->finish.hour,p->finish.minute,p->zz,p->zzxs);
		pz=pz+p->zz;
		px=px+p->zzxs;
		p=p->next;
	} 
	printf("系统平均周转时间为:\t\t\t\t\t\t\t\t\t%.2f\n",pz/n);
	printf("系统平均带权周转系数为:        \t\t\t\t\t\t\t\t\t\t%.2f\n",px/n);
}
//函数名:ScanIn()    参数:wait进程队列指针, n 进程数
time ScanIn(Queue* wait,int n){
	
	//函数功能:输入进程信息,返回最早的进程到达时间
	int count; 
	count=n;
	time N;
	Node *q;
	q=wait->tail;
	printf("请输入进程的参数:\nid号 名字 优先级 到达时间 执行时间(分钟):\n");
	 while(count--)
	 {
	 	Node *p=(Node *)malloc(sizeof(Node));
	 	p->next=NULL;
	 	scanf("%d %s %d %d:%d %d",&p->id,&p->name,&p->good,&p->arrive.hour,&p->arrive.minute,&p->zx);
	 	if(wait->front==NULL&&wait->tail==NULL)
	 	{
	 		wait->front=p;
	 		q=p;
	 		N.hour=p->arrive.hour;
	 		N.minute=p->arrive.minute;
		}
		else
		{
			q->next=p;
			q=p;
			wait->tail=p;
			if((p->arrive.hour<N.hour)||((p->arrive.hour==N.hour)&&(p->arrive.minute<N.minute)))
			{
				N.hour=p->arrive.hour;
	 			N.minute=p->arrive.minute;
			}
		}
	 }
	 return N;
}

int main(){
	
	Queue* wait;
	wait = init();
	int flag,n;
	time earlytime;
	
	while(1){
		printf("请输入操作:(1:开始进程;0:结束进程):");
		scanf("%d",&flag);
		if(flag == 0){
			printf("\n操作结束!\n");
			break; 
		} 
		else{
			printf("请输入进程数量:");
			scanf("%d",&n);
			earlytime = ScanIn(wait,n);//函数功能:输入进程信息,返回最早的进程到达时间
			LevelSorted(wait);//函数功能:对进程队列按优先级排序
			wait = priority(wait,earlytime,n);//函数功能:进行优先级进程调度,并同时更新当前时间。
			Print(wait,n);//函数功能:打印输出进程优先进程调度结果
			wait = init();
			
		}
	}
	
	return 0;

}

运行结果

实验总结

1、在开始实验之前必须有正确的设计思路

2、理解了优先级的进程调度,当时间和优先级冲突时,首先考虑优先级

3、如果有两个Node *p,q;则p=q和*p=*q的含义是不同的,前者表示两者指向同一个结点,后者表示赋值

4、单链表的创建和应用还不是很熟练,还得多加练习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1484245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCIe(四)—— 物理层

在看完事务层和数据链路层之后,我们来继续我们的协议栈之旅吧!这一篇中,我们会来看看PCIe物理层(Physical Layer)是如何工作的,从而帮助我们更加深入的了解PCIe的数据传输。 1. 物理层(Physical Layer) 当数据链路层将上层数据封装好后,就会将其交给物理层进行传输。…

探讨苹果 Vision Pro 的 AI 数字人形象问题

Personas 的设计模糊性&#xff1a; 部分人认为这种模糊设计可能是出于安全考虑&#x1f6e1;️。安全角度&#xff1a;Personas 代表着你的 AI 数字形象&#xff0c;在创建时&#xff0c;它相当于你的 AVP&#xff08;生物识别扫描器的存在增加了冒充的难度&#xff09;。如果…

第19章-IPv6基础

1. IPv4的缺陷 2. IPv6的优势 3. 地址格式 3.1 格式 3.2 长度 4. 地址书写压缩 4.1 段内前导0压缩 4.2 全0段压缩 4.3 例子1 4.4 例子 5. 网段划分 5.1 前缀 5.2 接口标识符 5.3 前缀长度 5.4 地址规模分类 6. 地址分类 6.1 单播地址 6.2 组播地址 6.3 任播地址 6.4 例子 …

ICLR/NeurIPS论文分享:任务通用的时序基础模型

吴海旭 清华大学软件学院博士生 师从龙明盛副教授&#xff0c;研究方向为深度学习及其在复杂时空物理过程建模中的应用&#xff0c;目前在Nature Machine Intelligence、IEEE TPAMI、ICML、NeurIPS上发表多篇论文&#xff0c;研究成果在中国气象局、北京冬奥会落地应用。曾获清…

Linux信号【systemV】

目录 前言 正文&#xff1a; 1消息队列 1.1什么是消息队列&#xff1f; 1.2消息队列的数据结构 1.3消息队列的相关接口 1.3.1创建 1.3.2释放 1.3.3发送 1.3.4接收 1.4消息队列补充 2.信号量 2.1什么是信号量 2.2互斥相关概念 2.3信号量的数据结构 2.4…

【高阶数据结构】LRUCache

文章目录 1. 什么是LRU Cache2. LRU Cache的实现3. LinkedHashMap4. LRU Cache OJ题4.1 题目要求4.2 解题思路4.3 代码实现4.3.1 Java代码一4.3.2 Java代码二 1. 什么是LRU Cache LRUCache&#xff0c;全称为Least Recently Used Cache&#xff0c;即最近最少使用缓存&#xf…

基于springboot+vue的纺织品企业财务管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

mac 安装hbuilderx

下载 HBuilderX下载地址: 下载地址 选额mac版本点击下载 安装 如图&#xff0c;将HBuilderX拖到Applications&#xff0c;才是正确的安装姿势。 MacOSX&#xff0c;软件必须安装到/Applications目录&#xff0c;如未安装到此目录&#xff0c;可能会出现插件安装失败、项目创建…

揭秘Java性能调优的层次 | 综合多方向提升应用程序性能与系统高可用的关键(架构层次规划)

揭秘性能调优的层次 | 综合多方向提升应用程序性能与系统的高可用 前言介绍调优层次调优 — 设计案例说明 - 操作轮询控制事件驱动 调优 — 代码案例说明 - ArrayList和LinkedList性能对比案例说明 - 文件读写实现方式的性能对比 调优 — JVMJVM架构分布JVM调优方向**JVM垃圾回…

Linux搭建SFTP服务器

案例&#xff1a;搭建SFTP服务器 SFTP&#xff08;SSH文件传输协议&#xff09; SFTP&#xff08;SSH文件传输协议&#xff09;是一种安全的文件传输协议&#xff0c;用于在计算机之间传输文件。它基于SSH&#xff08;安全外壳协议&#xff09;的子系统&#xff0c;提供了加密的…

EchoServer回显服务器简单测试

目录 工具介绍 工具使用 测试结果 工具介绍 github的一个开源项目,是一个测压工具 EZLippi/WebBench: Webbench是Radim Kolar在1997年写的一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL&#xff0c;测试网站在压力下工作的…

动态住宅IP vs 静态住宅IP,如何选择适合你的海外住宅IP?

随着数字时代的发展&#xff0c;网络已经成为了我们日常生活中不可或缺的一部分。在海外留学、旅游、工作或者进行电子商务等活动时&#xff0c;一个合适的住宅IP可以帮助我们保护个人隐私、确保网络连接的稳定性、提高在线服务的可靠性等。因此&#xff0c;选择适合自己的住宅…

ChatGPT科研与AI绘图及论文高效写作教程

原文链接&#xff1a;ChatGPT科研与AI绘图及论文高效写作教程 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电…

vos3000外呼系统如何修改话机注册端口

本文以vos3000为例&#xff0c;其他产品替换对应产品名称即可 修改配置文件地址 /home/kunshi/mbx3000/etc/softswitch.conf H323_RAS_PORT1719 H323 注册端口&#xff0c;可以用逗号&#xff08;,&#xff09;分隔多个端口 H323_RC4_RAS_PORT3719 H323 加密注册端口&#x…

redis03 八种数据类型

思维草图 String类型 字符串类型&#xff0c;是redis中最简单的存储类型&#xff0c;可以包含任何数据&#xff0c;例如jpg图片或者序列化的对象等&#xff0c;底层都是以字节数组形式存储&#xff0c;最大能存储512MB的数据。 常用命令 KEY命名规范 加前缀&#xff0c;分…

Vue3 循环渲染 v-for

v-for 指令&#xff1a;用于循环渲染列表数据。 v-for 指令&#xff1a;可以循环数组、对象、字符串【不常用】、指定次数【很少用】。 key 属性&#xff1a;用于给标签添加一个唯一的标识。 key 属性&#xff1a;推荐使用 id、手机号、身份证号、学号 等唯一值。 注&#…

如何查看docker容器里面运行的nginx的配置文件哪

要查看Docker容器内运行的Nginx配置文件的位置&#xff0c;你可以通过进入容器的shell环境来直接查看。Nginx的默认配置文件通常位于/etc/nginx/nginx.conf&#xff0c;而网站特定的配置文件通常位于/etc/nginx/conf.d/目录中。以下是步骤来查看这些配置文件&#xff1a; 步骤…

挑战杯 基于机器视觉的车道线检测

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

软考54-上午题-【数据库】-关系模式的范式-真题

一、范式总结 第一步&#xff0c;先求候选码&#xff0c;由此得到&#xff1a;主属性、非主属性。 二、判断部分函数依赖的技巧 【回顾】&#xff1a;部分函数依赖 &#xff08;X&#xff0c;Y&#xff09;——>Z&#xff1b; X——>Z 或者 Y——>Z 题型&#xff1a;给…

Vue2:路由history模式的项目部署后页面刷新404问题处理

一、问题描述 我们把Vue项目的路由模式&#xff0c;设置成history 然后&#xff0c;build 并把dist中的代码部署到nodeexpress服务中 访问页面后&#xff0c;刷新页面报404问题 二、原因分析 server.js文件 会发现&#xff0c;文件中配置的路径没有Vue项目中对应的路径 所以…