操作系统进程调度算法的模拟实现(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 繁忙型作业的系统。
算法模拟思路:
- 首先将输入的进程放入一个进程数组中,然后根据进程的到达时间进行排序,将最先到达的进程放入进程就绪队列中。
- 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,并将在此进程执行期间到达的进程依次加入进程就绪队列。
- 如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。
算法模拟:
//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 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);
}
最高优先级调度算法
进程的优先级可以分为,静态优先级或动态优先级:
- 静态优先级:创建进程时候,就已经确定了优先级了,然后整个运行时间优先级都不会变化;
- 动态优先级:根据进程的动态变化调整优先级,比如如果进程运行时间增加,则降低其优先级,如果进程等待时间(就绪队列的等待时间)增加,则升高其优先级,也就是随着时间的推移增加等待进程的优先级。
该算法也有两种处理优先级高的方法,非抢占式和抢占式:
- 非抢占式:当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
- 抢占式:当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。
但是依然有缺点,可能会导致低优先级的进程永远不会运行
算法模拟思路:
- 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
- 当队列不空时,从队头取出一个进程来执行,直至此进程执行完,设置一个变量记录此进程执行过程中所有到达的进程。
- 将这些到达的进程进行排序,按照进程优先权排序(权值小的先入)。然后将排序好的进程数组中的进程依次加入进程队列。(只排当前进程执行期间到达的进程)
- 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列。
算法模拟:
//优先权高者优先(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 效率;如果设得太长又可能引起对短作业进程的响应时间变长。
算法模拟思路:
- 首先也是按进程的到达时间进行排序。让最先到达的进程入队。
- 当队列不空时,从队头取出一个进程来执行。此时分两种情况:①如果当前进程的剩余服务时间不大于时间片大小,说明此次将会将这个进程执 行完毕,在此进程执行过程中到达的进程需要添加到进程就绪队列中,这时就可以输出 此进程执行完毕②如果当前进程的剩余服务时间大于时间片大小,还需将此进程执行过程中到达 的进程需要添加到进程就绪队列中,然后此进程的剩余服务时间减少时间片大小,此进 程重新进入进程就绪队列
- 此时也要考虑如果队列为空,但进程数组中仍存在未到达的进程,这时将要到达进程加入进程就绪队列
算法模拟:
//时间片轮转(RR)
void RR(program pro[], int num)
{printf("请输入时间片大小");int timeslice; scanf("%d", ×lice);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", ×lice);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语言版本)
前言:本文旨在分享如何使用c语言对操作系统中的部分进程调度算法进行模拟实现,以及算法描述的讲解,完整代码放在文章末尾,欢迎大家自行拷贝调用 目录 常见的调度算法 数据结构 先来先服务调度算法 算法模拟思路: …...
webbench压测工具
介绍 webbench是Linux下的一个网站压力测试工具,最多可以模拟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,是一个嵌入式、跨平台、免费的音频处理库。为嵌入式移动多媒体设备上的应用开发者提供标准化、高性能、低延迟的 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的内容如下: version: 3 services:registry:image: registrycontainer_name: registryvolumes:- ./registry…...
Python机器学习17——Xgboost和Lightgbm结合分位数回归(机器学习与传统统计学结合)
最近XGboost支持分位数回归了,我看了一下,就做了个小的代码案例。毕竟学术市场上做这种新颖的机器学习和传统统计学结合的方法还是不多,算的上创新,找个好数据集可以发论文。 代码实现 导入包 import numpy as np import pandas…...
C#编程学习
1. **C#简介**: - C#是一种现代的、面向对象的编程语言,由Microsoft开发。 - 它是.NET框架的一部分,用于开发Windows应用程序、Web应用程序和服务等。 2. **开发环境**: - 你可以使用Visual Studio或Visual Studio Code…...
关于vue 父级不使用子级某模块 (插槽替换)
父级: <template><div><MoreSupplements code"Xmgk" message"补充内容越多,越精准"><template #r-btn>xxx</template></MoreSupplements></div> </template> <script> import MoreSupplements fr…...
睿趣科技:抖音小店在哪里选品
随着抖音平台的日益火爆,越来越多的商家选择在抖音小店开设自己的店铺。然而,对于许多新手来说,如何选品却成为了一个难题。那么,抖音小店应该在哪里选品呢? 首先,我们可以从抖音平台上的热门商品入手。通过观察抖音上…...
量变引起质变:安卓改多了,就是自己的OS
最近小米也发布了自己的OS,其他也有厂家跟进。这是自华为鸿蒙之后,大家都说自己开发OS。对此,也是有很多争论的。 有人说,这些东西不都是安卓套壳或者改名吗?怎么就变成了自己的OS?这种观点对不对呢&#x…...
IDEA 之 在不更改操作系统用户名的情况下更改 ${USER} 变量?
如何在不更改操作系统用户名的情况下更改 IntelliJ IDEA 中的 ${USER} 变量 IDEA -> Help -> Edit Custom VM 添加如下内容 -Duser.nameusername这样在文件或者函数注释的时候会读取这个配置,而不会读取电脑登录用户名...
基于JAVA的天猫商场系统设计与实现,springboot+jsp,MySQL数据库,前台用户+后台管理,完美运行,有一万五千字论文
目录 演示视频 基本介绍 论文目录 系统截图 演示视频 基本介绍 基于JAVA的天猫商场系统设计与实现,springbootjsp,MySQL数据库,前台用户后台管理,完美运行,有一万五千字论文。 本系统在HTML和CSS的基础上…...
Redis学习
缓存定义 缓存是一个告诉数据交换的存储器,使用它可以快速的访问和操作数据。 常见缓存使用 本地缓存的常见使用:Spring Cache、MyBatis的缓存等 我的session存储和redis都放到缓存里面的,所有程序不管部署多少份,访问的都是r…...
uni-app:实现picker下拉列表的默认值设置
效果 分析 1、在data中将index8的初始值设置为-1,表示未选择任何选项: index8: -1, //选择的下拉列表下标 2、在bindPickerChange8事件处理函数中添加条件判断。如果选择的值是-1,则将this.index8设置为"请输入",否则将…...
基于NB-iot技术实现财物跟踪的EA01-SG定位模块方案
NB-iot无线数传模块可做财物防盗窃器,让你的财物可定位跟踪! 随着社会的发展,公共资源及共享资源的蓬勃发展,对资产管理和资产追踪有了新的需求,如:某儿童玩具车在商场外面提供车辆乘坐游玩服务࿰…...
挑战吧,HarmonyOS应用开发工程师
一年一度属于工程师的专属节日1024,多重活动亮相啦~ 参与活动即有机会获得HUAWEI Freebuds 5i 耳机等精美礼品! 点击“阅读原文”查看更多活动详情!...
图论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、创建或选择项目:如果你还没有创建项目…...
关于腾讯云轻量应用服务器性能测评,看这一篇文章就够了
腾讯云轻量应用服务器性能如何?为什么便宜是不是性能不行?腾讯云百科txybk.com从轻量应用服务器的CPU型号、处理器主频、内存、公网带宽、月流量和系统盘多方面来详细测评轻量性能,轻量应用服务器性价比高,并不是性能不行…...
HDFS集群NameNode高可用改造
文章目录 背景高可用改造方案实施环境准备配置文件修改应用配置集群状态验证高可用验证 背景 假定目前有3台zookeeper服务器,分别为zk-01/02/03,DataNode服务器若干; 目前HDFS集群的Namenode没有高可用配置,Namenode和Secondary…...
Spark集群中一个Worker启动失败的排错记录
文章目录 1 检查失败节点worker启动日志2 检查正常节点worker启动日志3 查看正常节点spark环境配置4 又出现新的ERROR4.1 报错解释4.2 报错解决思路4.3 端口报错解决操作 集群下电停机后再次启动时,发现其中一台节点的worker启动失败。 1 检查失败节点worker启动日…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
