当前位置: 首页 > news >正文

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

        前言:本文旨在分享如何使用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;
}



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

相关文章:

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

前言&#xff1a;本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现&#xff0c;以及算法描述的讲解&#xff0c;完整代码放在文章末尾&#xff0c;欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路&#xff1a; …...

webbench压测工具

介绍 webbench是Linux下的一个网站压力测试工具&#xff0c;最多可以模拟3万个并发连接去测试网站的负载能力。 https://soft.lnmp.com/test/webbench/ 安装非常简单 tar zxvf webbench-1.5.tar.gz cd webbench-1.5 make && make install会在当前目录生成webbench可执…...

HarmonyOS 音频开发指导:使用 OpenSL ES 开发音频播放功能

OpenSL ES 全称为 Open Sound Library for Embedded Systems&#xff0c;是一个嵌入式、跨平台、免费的音频处理库。为嵌入式移动多媒体设备上的应用开发者提供标准化、高性能、低延迟的 API。HarmonyOS 的 Native API 基于Khronos Group开发的OpenSL ES 1.0.1 API 规范实现&am…...

docker搭建个人镜像仓库

docker搭建个人镜像仓库 安装registry mkdir docker-registry cd docker-registry mkdir registry mkdr auth vim docker-compose.ymldocker-compose.yml的内容如下&#xff1a; version: 3 services:registry:image: registrycontainer_name: registryvolumes:- ./registry…...

Python机器学习17——Xgboost和Lightgbm结合分位数回归(机器学习与传统统计学结合)

最近XGboost支持分位数回归了&#xff0c;我看了一下&#xff0c;就做了个小的代码案例。毕竟学术市场上做这种新颖的机器学习和传统统计学结合的方法还是不多&#xff0c;算的上创新&#xff0c;找个好数据集可以发论文。 代码实现 导入包 import numpy as np import pandas…...

C#编程学习

1. **C#简介**&#xff1a; - C#是一种现代的、面向对象的编程语言&#xff0c;由Microsoft开发。 - 它是.NET框架的一部分&#xff0c;用于开发Windows应用程序、Web应用程序和服务等。 2. **开发环境**&#xff1a; - 你可以使用Visual Studio或Visual Studio Code…...

关于vue 父级不使用子级某模块 (插槽替换)

父级: <template><div><MoreSupplements code"Xmgk" message"补充内容越多,越精准"><template #r-btn>xxx</template></MoreSupplements></div> </template> <script> import MoreSupplements fr…...

睿趣科技:抖音小店在哪里选品

随着抖音平台的日益火爆&#xff0c;越来越多的商家选择在抖音小店开设自己的店铺。然而&#xff0c;对于许多新手来说&#xff0c;如何选品却成为了一个难题。那么&#xff0c;抖音小店应该在哪里选品呢? 首先&#xff0c;我们可以从抖音平台上的热门商品入手。通过观察抖音上…...

量变引起质变:安卓改多了,就是自己的OS

最近小米也发布了自己的OS&#xff0c;其他也有厂家跟进。这是自华为鸿蒙之后&#xff0c;大家都说自己开发OS。对此&#xff0c;也是有很多争论的。 有人说&#xff0c;这些东西不都是安卓套壳或者改名吗&#xff1f;怎么就变成了自己的OS&#xff1f;这种观点对不对呢&#x…...

IDEA 之 在不更改操作系统用户名的情况下更改 ${USER} 变量?

如何在不更改操作系统用户名的情况下更改 IntelliJ IDEA 中的 ${USER} 变量 IDEA -> Help -> Edit Custom VM 添加如下内容 -Duser.nameusername这样在文件或者函数注释的时候会读取这个配置&#xff0c;而不会读取电脑登录用户名...

基于JAVA的天猫商场系统设计与实现,springboot+jsp,MySQL数据库,前台用户+后台管理,完美运行,有一万五千字论文

目录 演示视频 基本介绍 论文目录 系统截图 演示视频 基本介绍 基于JAVA的天猫商场系统设计与实现&#xff0c;springbootjsp&#xff0c;MySQL数据库&#xff0c;前台用户后台管理&#xff0c;完美运行&#xff0c;有一万五千字论文。 本系统在HTML和CSS的基础上&#xf…...

Redis学习

缓存定义 缓存是一个告诉数据交换的存储器&#xff0c;使用它可以快速的访问和操作数据。 常见缓存使用 本地缓存的常见使用&#xff1a;Spring Cache、MyBatis的缓存等 我的session存储和redis都放到缓存里面的&#xff0c;所有程序不管部署多少份&#xff0c;访问的都是r…...

uni-app:实现picker下拉列表的默认值设置

效果 分析 1、在data中将index8的初始值设置为-1&#xff0c;表示未选择任何选项&#xff1a; index8: -1, //选择的下拉列表下标 2、在bindPickerChange8事件处理函数中添加条件判断。如果选择的值是-1&#xff0c;则将this.index8设置为"请输入"&#xff0c;否则将…...

基于NB-iot技术实现财物跟踪的EA01-SG定位模块方案

NB-iot无线数传模块可做财物防盗窃器&#xff0c;让你的财物可定位跟踪&#xff01; 随着社会的发展&#xff0c;公共资源及共享资源的蓬勃发展&#xff0c;对资产管理和资产追踪有了新的需求&#xff0c;如&#xff1a;某儿童玩具车在商场外面提供车辆乘坐游玩服务&#xff0…...

挑战吧,HarmonyOS应用开发工程师

一年一度属于工程师的专属节日1024&#xff0c;多重活动亮相啦~ 参与活动即有机会获得HUAWEI Freebuds 5i 耳机等精美礼品&#xff01; 点击“阅读原文”查看更多活动详情&#xff01;...

图论05-【无权无向】-图的广度优先BFS遍历-路径问题/检测环/二分图/最短路径问题

文章目录 1. 代码仓库2. 单源路径2.1 思路2.2 主要代码 3. 所有点对路径3.1 思路3.2 主要代码 4. 联通分量5. 环检测5.1 思路5.2 主要代码 6. 二分图检测6.1 思路6.2 主要代码6.2.1 遍历每个联通分量6.2.2 判断相邻两点的颜色是否一致 7. 最短路径问题7.1 思路7.2 代码 1. 代码…...

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

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

关于腾讯云轻量应用服务器性能测评,看这一篇文章就够了

腾讯云轻量应用服务器性能如何&#xff1f;为什么便宜是不是性能不行&#xff1f;腾讯云百科txybk.com从轻量应用服务器的CPU型号、处理器主频、内存、公网带宽、月流量和系统盘多方面来详细测评轻量性能&#xff0c;轻量应用服务器性价比高&#xff0c;并不是性能不行&#xf…...

HDFS集群NameNode高可用改造

文章目录 背景高可用改造方案实施环境准备配置文件修改应用配置集群状态验证高可用验证 背景 假定目前有3台zookeeper服务器&#xff0c;分别为zk-01/02/03&#xff0c;DataNode服务器若干&#xff1b; 目前HDFS集群的Namenode没有高可用配置&#xff0c;Namenode和Secondary…...

Spark集群中一个Worker启动失败的排错记录

文章目录 1 检查失败节点worker启动日志2 检查正常节点worker启动日志3 查看正常节点spark环境配置4 又出现新的ERROR4.1 报错解释4.2 报错解决思路4.3 端口报错解决操作 集群下电停机后再次启动时&#xff0c;发现其中一台节点的worker启动失败。 1 检查失败节点worker启动日…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型

在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重&#xff0c;适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解&#xff0c;并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...

Python学习(8) ----- Python的类与对象

Python 中的类&#xff08;Class&#xff09;与对象&#xff08;Object&#xff09;是面向对象编程&#xff08;OOP&#xff09;的核心。我们可以通过“类是模板&#xff0c;对象是实例”来理解它们的关系。 &#x1f9f1; 一句话理解&#xff1a; 类就像“图纸”&#xff0c;对…...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi&#xff0c;还有多少人在用&#xff1f; 去年&#xff0c;月之暗面创始人杨植麟别提有多风光了。90后清华学霸&#xff0c;国产大模型六小虎之一&#xff0c;手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水&#xff0c;单月光是投流就花费2个亿。 疯…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...