首页 > 其他分享 >【操作系统】实验:进度调度(2)

【操作系统】实验:进度调度(2)

时间:2024-08-26 22:24:28浏览次数:13  
标签:操作系统 pro 调度 next queue 进程 进度 time PCB

目录

一、实验目的

二、实验要求

三、实验步骤

四、核心代码

五、记录与处理

六、思考

七、完整报告和成果文件提取链接


一、实验目的

1、掌握高优先权调度算法

2、理解时间片、优先权、抢占等基本概念。

二、实验要求

1. 优先权属于静态优先权;

2. 进入 CPU 运行一个时间片;

3. 考虑事先给定优先权和短进程优先两种情况;

4. 考虑到达时间不同。

三、实验步骤

1. 创建多个进程,假定所有进程都是就绪状态,根据进程的到达时间进就绪队列,选择调度算法;

2. 按照所选调度算法,使进程在就绪队列中排序,队列中队头进程优先级最高,队尾优先级最低;

3. 初始状态直接让队头进程进 CPU,运行 1 个时间片;

4. 如果进程在 CPU 上运行时间和服务时间相等,则该进程不需进就绪队列,否则,进程进就绪队列;同时,根据进程的到达时间看是否有进程进就绪队列;

5. 每次调度时都要输出一次所有进程信息。

四、核心代码

void CopyProgram(PCB *pro1,PCB *pro2) {
	memcpy(pro1->name,pro2->name,sizeof(pro2->name));
	pro1->arrivetime=pro2->arrivetime;
	pro1->running_time=pro2->running_time;
	pro1->priority=pro2->priority;
	pro1->start_time=pro2->start_time;
	pro1->done_time=pro2->done_time;
	pro1->zztime=pro2->zztime;
	pro1->dqzztime=pro2->dqzztime;
}
 
void Queueinit(PCBQueue* queue) {
	if (queue == NULL) {
		return;
	}
	queue->size = 0;
	queue->LastProg = (PCB*)malloc(sizeof(PCB));
	queue->LastProg->next=NULL;//注意加了此句
	queue->firstProg = queue->LastProg;
}
 
void EnterQueue(PCBQueue* queue, PCB* pro) {
	//加入进程队列
	queue->LastProg->next = (PCB*)malloc(sizeof(PCB));
	queue->LastProg = queue->LastProg->next;
	queue->LastProg->arrivetime = pro->arrivetime;
	memcpy(queue->LastProg->name, pro->name, sizeof(pro->name));
	queue->LastProg->priority = pro->priority;
	queue->LastProg->running_time = pro->running_time;
	queue->LastProg->copyRunning_time = pro->copyRunning_time;
	queue->LastProg->start_time = pro->start_time;
	queue->LastProg->next=NULL;//注意加了此句
	queue->size++;
}
 
PCB* poll(PCBQueue* queue) {
	PCB *temp;
 
	temp = queue->firstProg->next;
	if (temp == queue->LastProg) {
		queue->LastProg = queue->firstProg;
		queue->LastProg->next=NULL;//注意加了此句
		queue->size--;
		return temp;
	}
	queue->firstProg->next = queue->firstProg->next->next;
	queue->size--;
 
	return temp;
}
 
void sortWithEnterTime(PCB pro[], int num) { //将进程按到达时间(arrivetime)全部排序
	int i,j;
	PCB temp;
 
	for (i = 1; i < num; i++) {
		for (j = 0; j < num - i; j++) {
			if (pro[j].arrivetime > pro[j + 1].arrivetime) {
				temp = pro[j];
				pro[j] = pro[j + 1];
				pro[j + 1] = temp;
			}
		}
	}
}
 
void EnterQueueOfRuntime(PCBQueue *ready_queue,PCB *program) { //按进程的运行时间,找到就绪队列中的相应位置并插入进去
	PCB *p,*q;
	p=ready_queue->firstProg->next;
	q=ready_queue->firstProg;
 
	while(p) {
		if(p->running_time>program->running_time) {
			program->next=p;
			q->next=program;
			break;
		}
		q=p;
		p=p->next;
	}
	if(!p) { //如果就绪队列为空或该进程的运行时间最长,则将其插入到队尾
		ready_queue->LastProg->next=program;
		ready_queue->LastProg=program;
		program->next=NULL;
	}
	ready_queue->size++;
}
 
void EnterQueueOfPriority(PCBQueue *ready_queue,PCB *program) {
	PCB *p,*q;
	p=ready_queue->firstProg->next;
	q=ready_queue->firstProg;
 
	while(p) {
		if(p->priority<program->priority) { //优先级大的先执行
			program->next=p;
			q->next=program;
			break;
		}
		q=p;
		p=p->next;
	}
	if(!p) {
		ready_queue->LastProg->next=program;
		ready_queue->LastProg=program;
		program->next=NULL;
	}
	ready_queue->size++;
}
 
void FCFS(PCB pro[], int num) {
	int time,done_time;
	int i,count,tt,pronum;
	float sum_T_time,sum_QT_time;
	PCB *curpro,*temp_PCB;
 
	printf("\n\t\t\t\t\t先来先服务算法进程调度模拟\n\n");
	printf("\t————————————————————————————————————————————————\n");
	count=0;
	PCB pro2[100];
	sortWithEnterTime(pro, num);                              //按照进入到达时间顺序排序
	PCBQueue* queue = (PCBQueue*)malloc(sizeof(PCBQueue));    //定义就绪队列
	Queueinit(queue);                                        //就绪队列初始化
	EnterQueue(queue, &pro[0]);                              //将第一个进程送入就绪队列中
	time = pro[0].arrivetime;                            //记录第一个进程的到达时间
	pronum = 1;                                          //记录当前的进程数量
	sum_T_time = 0, sum_QT_time = 0;                   // sum_T_time 记录总的周转时间 ,sum_QT_time 记录总的加权周转时间
	while (queue->size > 0) {
		curpro = poll(queue);                           //从进程队列中取出一个进程
		if (time < curpro->arrivetime){
			time = curpro->arrivetime;
		}
		done_time = time + curpro->running_time;               //  done_time   为该进程的结束时间(开始时间+CPU运行时间)
		curpro->start_time=time;
		curpro->done_time=done_time;
		curpro->zztime = done_time - curpro->arrivetime;//周转时间
		curpro->dqzztime = curpro->zztime / curpro->running_time;//带权周转时间              
		sum_T_time += curpro->zztime;                                      //  sum_T_time  总的周转时间更新
		sum_QT_time += curpro->dqzztime;                                     //  sum_T_time  总的带权周转时间更新
		for (tt = time; tt <= done_time && pronum < num; tt++) { //模拟进程的执行过程
			if (tt >= pro[pronum].arrivetime) {
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
		}
		CopyProgram(&pro2[count],curpro);
		PrintRunningprogram(&pro2[count]);
		count++;
		if(queue->size!=0) {
			printf("\t就绪队列:\n");
			printf("\t————————————————————————————————————————————————\n");
			printf("\t进程 到达时间  服务时间 优先级\n");
			temp_PCB=queue->firstProg->next;
			for(i=queue->size; i>0; i--) {
				printf("\t%s\t%d\t%d\t%d\n",temp_PCB->name,temp_PCB->arrivetime,temp_PCB->running_time,temp_PCB->priority);
				temp_PCB=temp_PCB->next;
			}
			printf("\t————————————————————————————————————————————————\n");
			printf("\n\n\n");
		} else {
			printf("\t无进程处于就绪状态!\n");
			printf("\t————————————————————————————————————————————————\n\n\n");
		}
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num) {
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	PrintSortOfRunningprogram(pro2,count);
	//Print(pro2,count);
	printf("\t平均周转时间为:%.2f\n", sum_T_time /num);
	printf("\t平均带权周转时间为:%.2f\n",sum_QT_time/num);
}

主函数代码:

int main() {
	int n, t = 1;
	int proNum,  choice;
	PCB pro[MAXSIZE],temp_pro[MAXSIZE];
 
	printf("\n\n\t\t\t\t\t<<-------------进程初始化----------——>>\n");
	printf("\t\t\t\t\t请输入进程的个数:");
	scanf("%d", &proNum);
	inputProgram(pro, proNum);
	while (t) {
		menu();
		memcpy(temp_pro, pro, (sizeof(pro) / sizeof(pro[0])) * sizeof(PCB));
		scanf("%d", &n);
		while (n <= 0 || n > 4) {
			printf("\t\t\t指令不正确,请重新输入指令: ");
			scanf("%d", &n);
		}
		system("cls");
		switch (n) {
			case 1: {
				FCFS(temp_pro, proNum);
				break;
			}
			case 2: {
 
				SJF(temp_pro, proNum);
				break;
			}
			case 3: {
				HPF(temp_pro, proNum);
				break;
			}
			case 4: {
				t=0;
				break;
			}
		}
		getchar();
		printf("\n\t按任意键继续.......");
		getchar();
		system("cls");
	}
	system("cls");
	printf("\n\n\t\t\t\t\t您已成功退出系统!!!\n");
 
	return 0;
}

五、记录与处理

输入的进程数据如下:

选择第三个:高优先级算法

按照高优先级进行输出结果:

六、思考

高优先权调度算法的弊端是什么?

高优先权调度算法是一种在计算机系统中用于进程或作业调度的算法,它根据进程的优先权(或优先级)来决定执行顺序。优先权高的进程或作业会被优先执行,而优先权低的则会被推迟执行。然而,这种算法也存在一些弊端:

1.低优先级进程饥饿:在高优先权调度算法下,如果系统中存在大量高优先级的进程,低优先级的进程可能会被持续推迟执行,导致它们的响应速度变慢,甚至长时间得不到执行,这种现象被称为“饥饿”。

2.恶意进程或病毒的影响:恶意进程或病毒可能会通过提高自己的优先权来占用系统资源,导致正常进程无法得到执行。这种情况下,系统的安全性和稳定性会受到影响。

3.可能导致系统资源浪费:如果高优先级的进程执行了很短的时间就放弃处理机,那么系统会频繁地进行进程切换,这会导致系统资源的浪费,降低系统的整体效率。

4.未考虑作业的紧迫程度:高优先权调度算法在决定执行顺序时,可能未充分考虑作业的紧迫程度,因此不能保证紧迫性作业会被及时处理。

为了克服这些弊端,可以采用一些优化措施,例如设置进程的最大执行时间以避免长时间占用CPU资源,或者采用动态优先级调度算法,根据进程的实际执行情况来动态调整进程的优先级。此外,还可以考虑引入高响应比优先调度算法,以更全面地考虑进程的执行需求。

综上所述,虽然高优先权调度算法能确保高优先级进程或作业得到优先处理,但也存在可能导致低优先级进程饥饿、受恶意进程或病毒影响、系统资源浪费以及未考虑作业紧迫程度等弊端。因此,在设计和实施此类算法时,需要充分考虑这些因素,并采取适当的优化措施。

七、完整报告和成果文件提取链接

链接:https://pan.baidu.com/s/1UbP6729pCluscVW0_9oI8w?pwd=1xki 
提取码:1xki 

标签:操作系统,pro,调度,next,queue,进程,进度,time,PCB
From: https://blog.csdn.net/m0_73970214/article/details/141575055

相关文章

  • 操作系统终止线程
    终止线程方法1:从线程入口函数中return,主线程除外。方法2:调用pthread_exit函数。voidpthread_exit(void*retval);retval-和线程过程函数的返回值语义相同。注意:在任何线程中调用exit函数都将终止整个进程。问题:主线程结束,子线程是否会跟着一起结束?主线程结束,并不会......
  • 【转载】Win11优化大小核调度(无需重启)
    出处:https://bbs.saraba1st.com/2b/thread-2140520-1-1.html打开隐藏电源管理选项:管理员模式运行cmd,分别输入:powercfg-attributesSUB_PROCESSOR7f2f5cfa-f10c-4823-b5e1-e93ae85f46b5-ATTRIB_HIDEpowercfg-attributesSUB_PROCESSOR93b8b6dc-0698-4d1c-9ee4-0644e900c85......
  • 在深度学习程序中显示美观的进度条(史上最全的tqdm使用大全)
    tqdm用例大全下载tqdm库基础用法跟列表结合使用带提示的进度条自己设置进度条和自己定义更新自定义进度条处理单位动态显示损失值对于跑深度学习的人来说,如何更直观的观察训练进度和模型损失是十分重要的事。好的深度学习代码,在训练过程中能够直观的给人呈现出进度和......
  • 5069-L430ERMW 控制器 负责调度各种资源
    5069-L430ERMW控制器是指能够按照预定程序自动执行控制任务的装置。在硬件层面,它通常包括程序计数器、指令寄存器、指令译码器、时序产生器和操作控制器等组成部分,这些部分协同工作,完成对整个系统或设备的控制和协调。控制器的基本功能任务分配:5069-L430ERMW控制器可以根......
  • [操作系统]IO多路复用
    从阻塞I/O到I/O多路复用阻塞I/O,是指进程发起调用后,会被挂起(阻塞),直到收到数据再返回。如果调用一直不返回,进程就会一直被挂起。因此,当使用阻塞I/O时,需要使用多线程来处理多个文件描述符。多线程切换有一定的开销,因此引入非阻塞I/O。非阻塞I/O不会将进程挂起,调用时会立......
  • [操作系统]阻塞io 非阻塞io Epoll
    BlockingI/O,NonblockingI/O,AndEpollJanuary10,2017InthispostIwanttoexplainexactlywhathappenswhenyouusenonblockingI/O.Inparticular,Iwanttoexplain:ThesemanticsofsettingO_NONBLOCKonafiledescriptorusingfcntlHownonblock......
  • 【Linux】理解操作系统中的进程状态:阻塞、挂起、运行
    理解操作系统中的进程状态:阻塞、挂起、运行1.进程状态概述2.阻塞(Blocked)3.挂起(Suspended)4.运行(Running)5.状态转换关系6.总结理解操作系统中的进程状态:阻塞、挂起、运行操作系统是管理计算机硬件和软件资源的核心部分,而进程管理则是操作系统中最重要的功能......
  • 第八周进度报告
    这周主要学习了常用API,SimpleDateFormat的应用,以及时间的表示常用APISimpleDateFormat格式化:把时间变成我们喜欢的格式解析:把字符串表示的时间变成Date对象importjava.text.SimpleDateFormat;importjava.util.Date;publicstaticvoidmain(String[]args)throw......
  • [操作系统]访问一个逻辑地址发生了什么
    当CPU想要访问一个逻辑地址的时候,我们需要做两个步骤,地址转换和内存访问地址转换逻辑地址是程序内部使用的地址,并非真正的物理地址。从逻辑地址到物理地址的映射,由页表来完成,页表的内容包括,逻辑页号,物理页号,有效位,有效位表示这一页是否在内存中。页表存放在内存中,如果需要频繁......
  • [操作系统]死锁
    死锁死锁是指在并发系统中,两个或多个进程因为互相等待对方释放资源而无法继续执行的状态。死锁发生的条件通常包括以下四个条件:互斥条件(MutualExclusion):至少有一个资源被标记为只能被一个进程占用,即一次只能有一个进程使用该资源。请求与保持条件(HoldandWait):一个进程在持......