当前位置: 首页 > 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启动日…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...