操作系统进程调度算法的模拟实现(c语言版本)

news2024/11/22 19:48:34

        前言:本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解,完整代码放在文章末尾,欢迎大家自行拷贝调用

目录

常见的调度算法

数据结构

先来先服务调度算法

算法模拟思路:

算法模拟: 

最短作业优先调度算法

算法模拟思路:

算法模拟:

 最高优先级调度算法

算法模拟思路:

算法模拟:

 时间片轮转调度算法

算法模拟思路:

算法模拟: 

完整代码:

 course.h: 

course.cpp:

test.cpp: 


常见的调度算法

  • 先来先服务调度算法
  • 最短作业优先调度算法
  • 高响应比优先调度算法
  • 最高优先级调度算法
  • 时间片轮转调度算法
  • 多级反馈队列调度算法
  • ... ...

数据结构

typedef struct program
{
	char name[20];
	int running_time;
	int enter_time;
	int priority;
	int done_time;			//用于时间片轮转
	int copyRunning_time;   //用于时间片轮转
	int start_time;
	program* next;
} Program;

typedef struct programQueue
{
	program* firstProg;
	program* LastProg;
	int size;
} programQueue;

 

先来先服务调度算法

        顾名思义,先来后到,每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。但是当一个长作业先运行了,那么后面的短作业等待的时间就会很长,不利于短作业。FCFS 对长作业有利,适用于 CPU 繁忙型作业的系统,而不适用于 I/O 繁忙型作业的系统。

算法模拟思路:

  1. 首先将输入的进程放入一个进程数组中,然后根据进程的到达时间进行排序,将最先到达的进程放入进程就绪队列中。
  2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,并将在此进程执行期间到达的进程依次加入进程就绪队列。
  3. 如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

算法模拟: 

//FCFS先来先服务算法
void FCFS(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);    //按照进入顺序排序 
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		sum_T_time += T_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_QT_time += QT_time;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
		}
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}

最短作业优先调度算法

        最短作业优先调度算法会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。这显然对长作业不利,很容易造成一种极端现象。比如,一个长作业在就绪队列等待运行,而这个就绪队列有非常多的短作业,那么就会使得长作业不断的往后推,周转时间变长,致使长作业长期不会被运行。

算法模拟思路:

  1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
  2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
  3. 将这些到达的进程进行排序,按照进程服务时间的大小。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
  4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

算法模拟:

//短作业优先算法
void SJF(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_T_time += T_time;
		sum_QT_time += QT_time;
		int pre = pronum;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pronum++;
			}
		}
		sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
		for (int i = pre; i < pronum; i++)
		{
			//将进程链入队列 
			EnterQueue(queue, &pro[i]);
		}
		pre = pronum;
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
}

 最高优先级调度算法

进程的优先级可以分为,静态优先级或动态优先级:

  • 静态优先级创建进程时候,就已经确定了优先级了,然后整个运行时间优先级都不会变化;
  • 动态优先级根据进程的动态变化调整优先级,比如如果进程运行时间增加,则降低其优先级,如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级,也就是随着时间的推移增加等待进程的优先级。

该算法也有两种处理优先级高的方法,非抢占式和抢占式:

  • 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
  • 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。

但是依然有缺点,可能会导致低优先级的进程永远不会运行

算法模拟思路:

  1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
  2. 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
  3. 将这些到达的进程进行排序,按照进程优先权排序(权值小的先入)。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
  4. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。

算法模拟:

//优先权高者优先(HPF)
void HPF(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_T_time += T_time;
		sum_QT_time += QT_time;
		int pre = pronum;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pronum++;
			}
		}
		sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
		for (int i = pre; i < pronum; i++)
		{
			//将进程链入队列 
			EnterQueue(queue, &pro[i]);
		}
		pre = pronum;
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}

 时间片轮转调度算法

        每个进程被分配一个时间段,称为时间片,即允许该进程在该时间段中运行。如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;如果时间片设得太短会导致过多的进程上下文切换,降低了 CPU 效率;如果设得太长又可能引起对短作业进程的响应时间变长。

算法模拟思路:

  1. 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
  2. 当队列不空时,从队头取出一个进程来执行。此时分两种情况:①如果当前进程的剩余服务时间不大于时间片大小,说明此次将会将这个进程执 行完毕,在此进程执行过程中到达的进程需要添加到进程就绪队列中,这时就可以输出 此进程执行完毕②如果当前进程的剩余服务时间大于时间片大小,还需将此进程执行过程中到达 的进程需要添加到进程就绪队列中,然后此进程的剩余服务时间减少时间片大小,此进 程重新进入进程就绪队列
  3. 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列

算法模拟: 

//时间片轮转(RR)
void RR(program pro[], int num)
{
	printf("请输入时间片大小");
	int timeslice; scanf("%d", &timeslice);
	printf("进程 到达时间  服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	pro[0].start_time = pro[0].enter_time;
	EnterQueue(queue, &pro[0]);
	int time = 0;
	int pronum = 1;
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);    // 从队列中取出头节点 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		if (timeslice >= curpro->running_time)
		{
			// 如果剩余时间小于时间片  则此任务完成
			for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
			{
				// 模拟进程的执行过程 
				if (tt >= pro[pronum].enter_time)
				{
					// 统计从此任务开始到结束之间有几个进程到达 
					pro[pronum].start_time = tt;
					EnterQueue(queue, &pro[pronum]);
					pronum++;
				}
			}
			time += curpro->running_time;
			curpro->running_time = 0;
			curpro->done_time = time;
			int T_time = curpro->done_time - curpro->start_time;
			float QT_time = T_time / (curpro->copyRunning_time + 0.0);
			sum_T_time += T_time;
			sum_QT_time += QT_time;
			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
				curpro->start_time, curpro->done_time, T_time, QT_time);
			if (queue->size == 0 && pronum < num)
			{
				//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
				pro[pronum].start_time = pro[pronum].enter_time;
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
			continue;
		}
		for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pro[pronum].start_time = tt;
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
		}
		time += timeslice;
		curpro->running_time -= timeslice;
		EnterQueue(queue, curpro);    //当前程序未完成  继续添加到队列中 
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			pro[pronum].start_time = pro[pronum].enter_time;
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}

完整代码:

我们分三个文件进行操作,当然大家也可以把三个文件按顺序放在一个文件里面进行操作

course.h:      结构体的包含以及函数的声明

course.cpp:  函数的具体实现

test.cpp:       主函数用于调用其余文件函数

 course.h: 

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

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

typedef struct program
{
	char name[20];
	int running_time;
	int enter_time;
	int priority;
	int done_time;			//用于时间片轮转
	int copyRunning_time;   //用于时间片轮转
	int start_time;
	program* next;
} Program;

typedef struct programQueue
{
	program* firstProg;
	program* LastProg;
	int size;
} programQueue;

//初始化
void Queueinit(programQueue* queue);

//打印
void print(program pro[], int num);

//打印队列
void printQueue(programQueue* queue);

//加入进程队列 
void EnterQueue(programQueue* queue, program* pro);

//查询
program* poll(programQueue* queue);

//输入
void inputProgram(program pro[], int num);

//根据时间排序
void sortWithEnterTime(program pro[], int num);

//FCFS先来先服务算法
void FCFS(program pro[], int num);

//根据长度排序
void sortWithLongth(program pro[], int start, int end);

//短作业优先算法
void SJF(program pro[], int num);

//根据优先级排列
void sortWithPriority(program pro[], int start, int end);

//优先权高者优先(HPF)
void HPF(program pro[], int num);

//时间片轮转(RR)
void RR(program pro[], int num);

//选择菜单
void choiceMenu();

course.cpp:

#define _CRT_SECURE_NO_WARNINGS 1
#include "course.h"

//初始化
void Queueinit(programQueue* queue)
{
	if (queue == NULL)
	{
		return;
	}
	queue->size = 0;
	queue->LastProg = (program*)malloc(sizeof(program));
	queue->firstProg = queue->LastProg;
}

//打印
void print(program pro[], int num)
{
	for (int i = 0; i < num; i++)
	{
		printf("%d ", pro[i].enter_time);
	}
}

//打印输出队列
void printQueue(programQueue* queue)
{
	program* p = queue->firstProg->next;
	while (p != NULL)
	{
		printf("%s ", p->name);
		p = p->next;
	}
	printf("\n");
}

//加入进程队列 
void EnterQueue(programQueue* queue, program* pro)
{
	queue->LastProg->next = (program*)malloc(sizeof(program));
	queue->LastProg = queue->LastProg->next;
	queue->LastProg->enter_time = pro->enter_time;
	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->size++;
}

//查询
program* poll(programQueue* queue)
{
	program* temp = queue->firstProg->next;
	if (temp == queue->LastProg)
	{
		queue->LastProg = queue->firstProg;
		queue->size--;
		return temp;
	}
	queue->firstProg->next = queue->firstProg->next->next;
	queue->size--;
	return temp;
}

//输入
void inputProgram(program pro[], int num)
{
	for (int i = 0; i < num; i++)
	{
		program prog;
		printf("请输入第%d个进程的名字,到达时间,服务时间,优先级\n", i + 1);
		scanf("%s", prog.name);
		scanf("%d", &prog.enter_time);
		scanf("%d", &prog.running_time);
		prog.copyRunning_time = prog.running_time;
		scanf("%d", &prog.priority);
		pro[i] = prog;
	}
}

//根据时间排序
void sortWithEnterTime(program pro[], int num)
{
	for (int i = 1; i < num; i++)
	{
		for (int j = 0; j < num - i; j++)
		{
			if (pro[j].enter_time > pro[j + 1].enter_time)
			{
				program temp = pro[j];
				pro[j] = pro[j + 1];
				pro[j + 1] = temp;
			}
		}
	}
}

//FCFS先来先服务算法
void FCFS(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);    //按照进入顺序排序 
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		sum_T_time += T_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_QT_time += QT_time;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
		}
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}

//根据长度排序
void sortWithLongth(program pro[], int start, int end)
{
	int len = end - start;
	if (len == 1) return;
	for (int i = 1; i < len; i++) {
		for (int j = start; j < end - i; j++)
		{
			if (pro[j].running_time > pro[j + 1].running_time)
			{
				program temp = pro[j];
				pro[j] = pro[j + 1];
				pro[j + 1] = temp;
			}
		}
	}
}

//短作业优先算法
void SJF(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_T_time += T_time;
		sum_QT_time += QT_time;
		int pre = pronum;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pronum++;
			}
		}
		sortWithLongth(pro, pre, pronum);//将到达的进程按照服务时间排序
		for (int i = pre; i < pronum; i++)
		{
			//将进程链入队列 
			EnterQueue(queue, &pro[i]);
		}
		pre = pronum;
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / num);
}

//根据优先级排列
void sortWithPriority(program pro[], int start, int end)
{
	int len = end - start;
	if (len == 1) return;
	for (int i = 1; i < len; i++)
	{
		for (int j = start; j < end - i; j++)
		{
			if (pro[j].priority > pro[j + 1].priority)
			{
				program temp = pro[j];
				pro[j] = pro[j + 1];
				pro[j + 1] = temp;
			}
		}
	}
}


//优先权高者优先(HPF)
void HPF(program pro[], int num)
{
	printf("进程 到达时间  服务时间 开始时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	EnterQueue(queue, &pro[0]);
	int time = pro[0].enter_time;
	int pronum = 1;    //记录当前的进程 
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);   //从进程队列中取出进程 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		int done_time = time + curpro->running_time;
		int T_time = done_time - curpro->enter_time;
		float QT_time = T_time / (curpro->running_time + 0.0);
		sum_T_time += T_time;
		sum_QT_time += QT_time;
		int pre = pronum;
		for (int tt = time; tt <= done_time && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pronum++;
			}
		}
		sortWithPriority(pro, pre, pronum);//将到达的进程按照服务时间排序
		for (int i = pre; i < pronum; i++)
		{
			//将进程链入队列 
			EnterQueue(queue, &pro[i]);
		}
		pre = pronum;
		printf("%s\t%d\t%d\t%d\t%d\t%d\t%.2f\n", curpro->name, curpro->enter_time, curpro->running_time, time, done_time, T_time, QT_time);
		time += curpro->running_time;
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}



//时间片轮转(RR)
void RR(program pro[], int num)
{
	printf("请输入时间片大小");
	int timeslice; scanf("%d", &timeslice);
	printf("进程 到达时间  服务时间 进入时间 完成时间 周转时间 带权周转时间\n");
	sortWithEnterTime(pro, num);
	programQueue* queue = (programQueue*)malloc(sizeof(programQueue));
	Queueinit(queue);
	pro[0].start_time = pro[0].enter_time;
	EnterQueue(queue, &pro[0]);
	int time = 0;
	int pronum = 1;
	float sum_T_time = 0, sum_QT_time = 0;
	while (queue->size > 0)
	{
		program* curpro = poll(queue);    // 从队列中取出头节点 
		if (time < curpro->enter_time)
			time = curpro->enter_time;
		if (timeslice >= curpro->running_time)
		{
			// 如果剩余时间小于时间片  则此任务完成
			for (int tt = time; tt <= time + curpro->running_time && pronum < num; tt++)
			{
				// 模拟进程的执行过程 
				if (tt >= pro[pronum].enter_time)
				{
					// 统计从此任务开始到结束之间有几个进程到达 
					pro[pronum].start_time = tt;
					EnterQueue(queue, &pro[pronum]);
					pronum++;
				}
			}
			time += curpro->running_time;
			curpro->running_time = 0;
			curpro->done_time = time;
			int T_time = curpro->done_time - curpro->start_time;
			float QT_time = T_time / (curpro->copyRunning_time + 0.0);
			sum_T_time += T_time;
			sum_QT_time += QT_time;
			printf("%s\t%d\t%d\t  %d\t   %d\t %d\t  %.2f\n", curpro->name, curpro->enter_time, curpro->copyRunning_time,
				curpro->start_time, curpro->done_time, T_time, QT_time);
			if (queue->size == 0 && pronum < num)
			{
				//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
				pro[pronum].start_time = pro[pronum].enter_time;
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
			continue;
		}
		for (int tt = time; tt <= time + timeslice && pronum < num; tt++)
		{
			//模拟进程的执行过程 
			if (tt >= pro[pronum].enter_time)
			{
				// 统计从此任务开始到结束之间有几个进程到达 
				pro[pronum].start_time = tt;
				EnterQueue(queue, &pro[pronum]);
				pronum++;
			}
		}
		time += timeslice;
		curpro->running_time -= timeslice;
		EnterQueue(queue, curpro);    //当前程序未完成  继续添加到队列中 
		if (queue->size == 0 && pronum < num)
		{
			//防止出现前一个进程执行完到下一个进程到达之间无进程进入 
			pro[pronum].start_time = pro[pronum].enter_time;
			EnterQueue(queue, &pro[pronum]);
			pronum++;
		}
	}
	printf("平均周转时间为%.2f\t平均带权周转时间为%.2f\n\n", sum_T_time / (num + 0.0), sum_QT_time / (num + 0.0));
}

//选择菜单
void choiceMenu()
{
	printf("请选择进程调度算法:\n");
	printf("1.先来先服务算法\n");
	printf("2.短进程优先算法\n");
	printf("3.高优先级优先\n");
	printf("4.时间片轮转算法\n");
}

test.cpp: 

#define _CRT_SECURE_NO_WARNINGS 1
#include"course.h"

int main()
{
	int proNum = 5;		//5个进程
	program pro[5];
	inputProgram(pro, proNum);
	choiceMenu();
	int choice;
	do
	{
		scanf("%d", &choice);
		switch (choice)
		{
		case 1:
			system("cls");
			FCFS(pro, proNum);
			choiceMenu();
			break;
		case 2:
			system("cls");
			SJF(pro, proNum);
			choiceMenu();
			break;
		case 3:
			system("cls");
			HPF(pro, proNum);
			choiceMenu();
			break;
		case 4:
			system("cls");
			RR(pro, proNum);
			choiceMenu();
			break;
		default:
			printf("输入错误,请重新尝试\n");
			break;
		}
	} while (choice);

	return 0;
}



本次的分享就到此为止了,感谢您的支持,如果您有不同意见,欢迎评论区积极交流

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

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

相关文章

LeetCode刷题---简单组(三)

文章目录 &#x1f352;题目一 20. 有效的括号&#x1f352;解法一&#x1f352;题目二 26. 删除有序数组中的重复项&#x1f352;解法一&#x1f352;题目三 21. 合并两个有序链表&#x1f352;解法一 &#x1f352;题目一 20. 有效的括号 给定一个只包括 ‘(’&#xff0c;‘…

Q-learning智能体

Q-learning智能体 Q-learning算法是一种无模型、在线、非策略的强化学习方法。Q-learning算法是一种基于价值的强化学习算法&#xff0c;它训练一个评价网络去估计回报或未来奖励。对于给定的观测值&#xff0c;智能体选择并输出估计收益最大的动作。 注&#xff1a;Q-learnin…

PL/SQL工具下载地址

https://www.allroundautomations.com/registered-plsqldev/ 选择需要下载的版本即可

Shopee、Lazada卖家不得不看的提升销量技巧,自养号测评打造权重

近年来&#xff0c;大部分虾皮、Lazada卖家开始通过测评补单的方式来提升店铺权重和产品排名&#xff0c;以吸引更多流量。这种方式可以有效提高产品的销售转化率&#xff0c;对店铺的运营起到推动作用。然而&#xff0c;测评补单并非简单的购买过程&#xff0c;其中涉及到许多…

网页提示证书错误 怎么办

随着网站使用SSL证书来加密网站信息&#xff0c;SSL证书的应用也越来越广泛&#xff0c;那么有时候我们进入网站&#xff0c;明明安装了SSL证书&#xff0c;为什么也会提示证书错误呢&#xff1f; SSL证书错误可能是由以下原因导致的&#xff1a; 1. 证书过期&#xff1a; SSL证…

推荐一个假数据接口网页 适用于示例项目

DummyJSON - Fake REST API of JSON data for development

全面分享‘’找不到msvcp140.dll无法继续执行代码修复教程

计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll缺失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要找到合适的解决办法。本文将介绍5种解决msvcp140.dll缺失问题的方法&#xff0c;帮…

【实战】硅基物语.AI写作高手:从零开始用ChatGPT学会写作

文章目录 从零开始使用ChatGPT学习写作一、简介二、ChatGPT写作的优势1. 提高效率2. 丰富的素材库3. 语言多样性4. 智能纠错 三、如何使用ChatGPT学习写作1. 确定写作目标和受众2. 了解ChatGPT的原理和特点3. 选择合适的模型和训练数据4. 制定写作计划和流程5. 不断实践和优化 …

管理员|顾问必看!8个Salesforce权限集的最佳实践

Salesforce中的权限一直始终是热门话题。权限集是简档的附加。它们通常具有相同的设置&#xff0c;用于增加用户的权限&#xff0c;使其超过简档提供的权限。可以将简档视为许多用户共有的基本权限集&#xff0c;而权限集是部分用户需要的额外权限。 本篇文章将介绍Salesforce…

Altium Designer元件库封装

资料 立创商城&#xff1a;https://www.szlcsc.com/ 立创EDA&#xff1a;https://pro.lceda.cn/ 库创建项目 项目创建 文件→新建→项目→PCB 新建原理图库 项目&#xff08;反键&#xff09;→添加新的…到工程→Schematic Library 新建PCB库 项目&#xff08;反键&…

【注意!水群需谨慎】手把手教你使用Python实时监测QQ群消息

文章目录 1. 写在前面2. 下载源码构建3. 通过release部署4. 运行本地服务5. 通过API获取数据6. 完整代码实现 1. 写在前面 前段时间写了一个QQ群消息监测的自动化机器人&#xff0c;需求则是加入到某些特定的群组&#xff0c;对群内对话消息进行实时监测与分析。当然&#xff0…

uniapp:谷歌地图,实现地图展示,搜索功能,H5导航

页面展示 APP H5 谷歌地图功能记录,谷歌key申请相对复杂一些,主要需要一些国外的身份信息。 1、申请谷歌key 以下是申请谷歌地图 API 密钥的流程教程: 登录谷歌开发者控制台:打开浏览器,访问 Google Cloud Platform Console。 1、创建或选择项目:如果你还没有创建项目…

智能低代码洪流涌动程序员节 华为云Astro触发1024的乘法效应

从人工智能至量子计算&#xff0c;再到最新的云原生技术&#xff0c;越来越多的荣耀被程序员斩获。今年1024程序员节&#xff0c;华为云Astro向全民致敬&#xff1a;「低代码高产出 拓荒数字化版图——人人皆是程序员」&#xff0c;为全球工程师及开发爱好者呈现智能化开发的魅…

北京筑龙发声炼化企业大会,助力央国企采购供应链数字化转型

10月25日&#xff0c;以“科技创新引领高质量发展&#xff0c;夯实炼化自立自强根基”为主题的第四届炼化企业创新发展大会暨新技术与解决方案交流会”在浙江省宁波市盛大召开。北京筑龙智能化业务部高级咨询顾问王良受邀出席&#xff0c;带来主题为“智能物料——企业采购供应…

FreeRTOS学习day1任务创建(动态创建)

顾名思义 免费的实时操作系统 用法基本和Linux下的多线程编程类似 探索者开发版实验 动态创建4个任务start_task task1 task2 task3 优先级依次为1 2 3 4 &#xff08;注意优先级不能为0,0是空闲任务&#xff09; 我的理解&#xff1a;主线程start_task 主线程 task1 ta…

uniapp接口请求api封装,规范化调用

封装规范和vue中的差不多&#xff0c;都是统一封装成一个request对象&#xff0c;然后在api.js里面调用。 先创建一个utils文件夹&#xff0c;然后里面创建一个request.js&#xff0c;代码如下&#xff1a; export const baseURL 基础url地址const request (options) > …

k8s-----25、资源调度-ResourceQuota资源配额、资源限制limitrange、服务质量QoS

1、ResourceQuota资源配额 1.0 作用 命名空间资源配额。防止公司内部人员对资源的不合理利用。 1.1、为什么需要资源配额 1、作为k8s集群的管理员&#xff0c;知道集群的规模&#xff0c;会合理规划资源&#xff0c;但是使用侧不知道&#xff0c;会导致很多不合理的使用场景…

ffmpeg的下载和编译(vs2022)

感谢大佬的二创,直接提供了sln编译 ffmpeg二创地址 创建如下目录 build存放代码(build最好改成source,因为作者这么建议,编译完才发现) msvc存放第三方依赖的头文件,这里固定叫msvc,因为大佬的sln里查找的路径是这个,不嫌麻烦也可以自己改 下载代码和编译器 下载源码…

Qt5 Python-docx库的使用,Qt python混合编程,qt 读写word,不依赖office

解决方案的选择 参考&#xff1a; https://www.jianshu.com/p/be68884849c3 因为项目要求不能使用模板方案&#xff0c;不能依赖Office&#xff0c;网上找了一些解决方案进行调研&#xff0c;以下几个方案&#xff1a; OpenOffice: 兼容性差&#xff0c;集成调用难度大LibOffi…

Mac怎么删除文件和软件?苹果电脑删除第三方软件方法

Mac删除程序这个话题为什么一直重复说或者太多人讨论呢&#xff1f;因为如果操作不当&#xff0c;可能会导致某些不好的影响。因为Mac电脑如果有太多无用的应用程序&#xff0c;很有可能会拖垮Mac系统的运行速度。或者如果因为删除不干净&#xff0c;导致残留文件积累在Mac电脑…