注:

本文是四个调度算法的第一篇算法。

本文是根据CSDN上某一FCFS调度算法魔改来的,所以FCFS的算法不会发到网站。

我是个菜鸡,发文是为了纪念自己完成了代码,以及累计自己的经验。

如有知识错误或者算法有逻辑漏洞请各位大佬高抬贵手。

实验环境:win10、VS2019(C++)

PS:虽然是cpp文件,实际上是披着cpp的c

运行前,首先要在预处理器上插入_CRT_SECURE_NO_WARNINGS,避免运行错误,在插入前要用;隔开。

具体位置就在解决方案下面一栏(名字是自己起的),右键属性即可找到。

这个核心代码相对于之前的最短优先算法SJF来说在判断单元节点到达时间上是一致的,只不过多了等待时间变量wait以及响应比计算函数hrn,内容相对稀少,所以本篇会详细介绍响应比hrn函数以及在SJF中没提到的其他模板函数。

注:如果想了解SJF算法或是判断单元节点到达时间函数此处为链接:C语言 操作系统实验 四种调度(最短优先算法SJF)_key_149的博客-CSDN博客

好了直接进正题

最高响应比算法除了单元节点到达时间的思路外,只有一个核心:响应比的计算

先上代码:

void hrn(JCB* p)//响应比计算函数,第一轮计算时wait == p->tr
{hr2 = hr;hr = (wait - p->tr) / p->tn;if (wait % p->tn){hr = hr + 1;}
}

响应比 = 响应时间 / 预计执行时间

响应时间 = 等待时间 + 预计执行时间

综上:响应比 = 1 + 作业等待时间  / 预计执行时间

而通过观察能发现,1是所有响应比都需要加的一个不变的常量,而在实际的代码编写当中可以省略,而关键的就在于会变的两个变量:等待时间、预计执行时间;

接下来就要对这两个变量进行分析:

预计执行时间:每个单元节点都有自己的预计执行时间当指针遍历某一单元节点时,就能获取当前节点的预计执行时间,而每个单元节点内的预计执行时间也是不会改变的。这样只需在遍历链表时直接计算响应比并进行记录便可。(在代码段中hr2代表的就是上一个进程的响应比,hr则是当前的响应比。)

等待时间:在第一个单元节点输出时,此时等待时间为0,是没有响应比的。所以在对链表头进行比较时,仅需对提交时间进行比较即可。在链表输出一次后,等待时间wait便是当前节点的执行时间 + 提交时间。但要注意的是这个等待时间并不包含与下一个单元节点的提交时间相交的部分,很有可能某个进程在上一个进程执行时的任意时刻到达,所以要减去它的提交时间,即 (wait - p->tr)出现的原因。

除了正常的公式计算,hrn函数中还包含了一个if语句,在C/C++中float类型的函数是不能被比较的,所以响应比的类型是int,而除出来的商也会是整数类型,在这种前提条件下极有可能出现响应比是小数的情况,进而使其和真正能整除的响应比混在一起,此时响应比+1以避免这种情况产生。

通过对这两个变量的总结可以得知:

1.在对链表头的的排序中,仅需要记录头结点的等待时间 + 执行时间;即wait = p->tr + p->tn;对于不断变换的头结点,wait也会相应的不断刷新。

2.至于头结点后的单元节点的排序是按提交时间排序即可。(与SJF思路类似,以便分层)

3.对于响应比会在输出每个单元节点后进行变化,所以响应比hrn函数应在遍历单元节点时逐一运行。

4.wait函数是在单元节点释放前加上当前的执行时间(头结点例外)

这样hrn的核心思路就捋清楚了,接下来上完整代码:

#include "stdio.h"
#include <stdlib.h>
#include <conio.h>
#define getpch(type) (type*)malloc(sizeof(type))
#define NULL 0//定义作业jcb结构体
struct jcb
{char name[100];int tr;//作业提交时间int tn;//作业运行时间int ts;//作业开始时间int tf;//作业完成时间float ti;//作业周转时间float wi;//作业带权周转时间int flag;//顺序struct jcb* link;
}*ready = NULL, * h, * p;
typedef struct jcb JCB;
JCB* first, * second, * last;int time = 0;
int num = 0; //作业数量
int sum = 0;//目前总时间
float eti = 0.0;
float ewi = 0.0;
int wait;//等待时间
int hr = 0;
int hr2 = 0;void hrn(JCB* p)//响应比计算函数,第一轮计算时wait == p->tr
{hr2 = hr;hr = (wait - p->tr) / p->tn;if (wait % p->tn){hr = hr + 1;}
}void linkpcb()//先将链表尾插法连接起来 //如果行不通就执行方案2 即将这些先按到达顺序排序后,通过dolevel进行分层,在用sort进行最短排序
{int insert = 0;if ((ready == NULL) || ((p->tr) <= (ready->tr) && p->tn < ready->tn)) /*提交 兼 提交 时间最小者,插入队首*/{p->link = ready;ready = p;wait = p->tr + p->tn;//计算首位的等待时间}else /* 进程比较提交时间,插入适当的位置中*/{first = ready;second = first->link;while (second != NULL){if ((p->tr) < (second->tr)) /*若插入作业比当前作业提交时间小,*/{p->link = second;//p插入到second前面first->link = p;second = NULL;//second只能在连接好的链表上运行insert = 1;}else /* 插入进程提交时间最高,则插入到队尾*/{first = first->link;second = second->link;}}if (insert == 0) first->link = p;//循环到最后若依旧没有比second大的,则first此时是p的前一个}
}void dolevel()
{if (second->tr <= sum){sum = sum + second->tn;}else{sum = second->tr + second->tn;second->flag = 0;}second = second->link;}void destroy() /*建立作业撤消函数(进程运行结束,卸载作业)*/
{free(p);
}
void running() /* 建立作业就绪函数(作业运行时间到,置就绪状态*/
{if (p->link == NULL)destroy(); /* 调用destroy函数*/
}
void disp(JCB* pr) /*建立作业显示函数,用于显示当前作业*/
{printf(" %s\t", pr->name);printf(" %d\t", pr->tr);printf(" %d\t", pr->tn);printf(" %d\t", pr->ts);printf(" %d\t", pr->tf);printf(" %-0.2f\t", pr->ti);printf(" %-0.2f\t", pr->wi);printf("\n");}
void check() /* 建立作业查看函数 */
{//累加变量time 记录当前用时 !!!if (time >= p->tr){p->ts = time;p->tf = p->ts + p->tn;time = p->tf;}else{p->ts = p->tr;p->tf = p->ts + p->tn;time = p->tf;}p->ti = p->tf - p->tr;p->wi = p->ti / p->tn;//!!!}void sort() /* 建立对作业进行提交时间排列函数,分出第一层*/
{first = ready;//first归位p = ready;last = ready;if (last->flag == 0)//置1{last->flag = 1;}while ((last->flag == 1 && last->link != NULL))//一层中找到最小的  最后一个会被强制退出{hrn(last);if (hr > hr2){p = last;}last = last->link;if (last->link == NULL)//在最后一个被踢出前先进行比较{hrn(last);if (hr > hr2){p = last;}}}wait = wait + p->tn;hr = 0;hr2 = 0;last = p->link;if (ready == p)//防止最小可能是头单元节点造成ready成空指针{ready = ready->link;}first->link = last;p->link = NULL;check();disp(p);eti += p->ti;ewi += p->wi;running();
}void input() /* 建立作业控制块函数*/
{int i;printf("\n 请输入即将运行的进程总数目");scanf("%d", &num);for (i = 0; i < num; i++){p = getpch(JCB);printf("\n 输入作业名:");scanf("%s", p->name);printf("\n 输入作业提交时间:");scanf("%d", &p->tr);printf("\n 输入作业运行时间:");scanf("%d", &p->tn);printf("\n");p->ts = 0;p->tf = 0;p->ti = 0.0f;p->wi = 0.0f;p->link = NULL;p->flag = 1;wait = p->tr;linkpcb();}p->link = NULL;printf("\n 名称 \t 提交 \t 运行 \t 开始 \t 完成 \t 周转\t 带权周转 \n");second = ready->link;//第二个sum = ready->tr + ready->tn;p = ready;check();//对最先到达那个进行特殊输出disp(p);eti += p->ti;ewi += p->wi;ready = ready->link;p->link = NULL;running();hrn(p);//记录当前响应比值do{dolevel();} while (second->link != NULL);//second此时是末尾节点for (i = 1; i < num; i++){sort(); /* 调用sort函数,对提交顺序和执行时间进行比较*/}}int main() /*主函数*/
{input();//此时已经按提交顺序排好了eti /= num;ewi /= num;printf("\n该组作业平均周转时间为:%0.2f", eti);printf("\n该组作业平均带权周转时间为:%0.2f", ewi);return 0;
}

这里需要注意一点:dolevel函数在运行时是计算当前时间sum的,但 sum != wait;sum的作用是为链表分层,而wait是随响应比变化的单元节点等待时间。这也就意味着响应比小的节点不一定是提交时间早的节点。

到此HRN的思路就截止了,接下来是链表模板函数的分析:

1.结构体jcb,在结构体中定义了每一结构体内的项目,如提交时间、等待时间等。在结构体设置完后要设置结构体变量,此处是指针变量* ready、* p等。

2.typedef struct jcb JCB;此行代码是用typedef定义一个类型,类型是结构体struct,结构体的名字jcb,而这个用typedef定义的名为jcb的结构体怎么表示呢?在此处命名为JCB。同样的JCB定义的指针first、second以及last。而理论上这三个指针变量和ready、p是一样的。

3.定义这个类型,还需要做一些准备工作:#define getpch(type) (type*)malloc(sizeof(type))
此行代码宏定义了申请即getpch,申请的类型是type类型,即2中的typedef,malloc是向机器申请空间,空间的大小为sizeof测量的type类型的大小。

4.在input函数中设置循环,对每个申请的空间进行初始化以及输入工作。

5.check()函数负责计算周转时间和带权周转时间,周转时间有两个算法:

执行时间 + 等待时间;

完成时间 - 提交时间;

带权周转时间公式:周转时间 / 执行时间;

6.在disp输出后,p->NULL;作为一个标记,而running()则是通过p->NULL作为判断可以运行销毁函数destory;而running函数本身是作为进程工作而设立的函数,此处仅用于调用销毁函数。

C语言 操作系统实验 四种调度(最高响应比优先算法 HRN)相关推荐

  1. 操作系统实验4—磁盘调度

    操作系统实验4-磁盘调度 文章目录 操作系统实验4-磁盘调度 实验描述 设计思路 上机代码 测试结果 心得体会 实验描述 实验内容: 编写一个磁盘调度程序,模拟操作系统对磁盘的调度. 实验目的: 本实 ...

  2. 操作系统实验四-LRU算法的模拟

    操作系统实验四:页式虚拟存储管理的模拟 一.实验目的: 掌握存储管理的基本原理.地址变换过程:用软件实现地址转换过程:用一种常用的页面置换算法来处理缺页中断并研究其命中率. 二.实验题目: 1.模拟请 ...

  3. 操作系统实验四——使用命名管道实现进程通信

    操作系统实验四--使用命名管道实现进程通信 一. 实验目的 (1)了解windows系统环境下的进程通讯机制. (2)熟悉Windows系统提供的进程通信API. 二. 实验准备 相关API函数介绍 ...

  4. c语言百人搬百砖答案,C语言程序设计实验四:循环结构

    C语言程序设计实验四:循环结构 1. 编写求n!的程序:要求输入n,然后计算输出n的阶乘. #include "stdio.h" void main() { long i,fac, ...

  5. 广州大学2020操作系统实验四:文件系统

    相关资料 广州大学2020操作系统实验一:进程管理与进程通信 广州大学2020操作系统实验二:银行家算法 广州大学2020操作系统实验三:内存管理 广州大学2020操作系统实验四:文件系统 广州大学2 ...

  6. matlab信息隐藏算法,实验四--基于DCT域的信息隐藏算法

    <实验四--基于DCT域的信息隐藏算法>由会员分享,可在线阅读,更多相关<实验四--基于DCT域的信息隐藏算法(6页珍藏版)>请在人人文库网上搜索. 1.实验四 基于DCT域的 ...

  7. 实验四 手写数字识别的神经网络算法设计与实现

    实验四 手写数字识别的神经网络算法设计与实现 一.实验目的 通过学习BP神经网络技术,对手写数字进行识别,基于结构的识别法及模板匹配法来提高识别率. 二.实验器材 PC机 matlab软件 三.实验内 ...

  8. 模式识别 实验四 手写数字识别的神经网络算法设计与实现

    实验四 手写数字识别的神经网络算法设计与实现 一.实验目的 通过学习BP神经网络技术,对手写数字进行识别,基于结构的识别法及模板匹配法来提高识别率. 二.实验器材 PC机 matlab软件 三.实验内 ...

  9. 一、操作系统——处理机(作业)调度算法:先来先服务算法FCFS、最短作业优先算法SJF(非抢占式)、 最短剩余时间优先算法SRTN(抢占式)、最高响应比优先算法HRRN

    各种调度算法的学习思路: 调度算法的评价指标: 一.先来先服务算法(FCFS):First Come First Serve 二.最短作业优先算法(SJF非抢占式):Shortest Job Firs ...

最新文章

  1. linux字符界面教程,打造字符界面的多媒体Linux系统
  2. Linux文件存储结构,包括目录项、inode、数据块
  3. 倒排列表求交集算法汇总
  4. Java 代码的基本知识
  5. MyBatis 事务源码分析
  6. 中文新闻分类 数据集_三亚试点用大数据推行垃圾分类:刷卡扔垃圾,分类有奖励|界面新闻...
  7. 国内搜索大哥iOS面试题
  8. ubantu 系统安装apache 和mysql
  9. 抛开复杂的架构设计,MySQL优化思想基本都在这了
  10. android viewpage 代码添加view,百行代码实现Android ViewPage指示器
  11. GO 打开WINDOWS的默认浏览器
  12. 页面status:500,报错 server encountered an internal error that prevented it from fulfilling this request.
  13. CodeLite13避免中文乱码的方法
  14. 在CentOS8.4中安装OpenFOAM
  15. QingCloud首届用户大会亮点抢先看
  16. labview入门范例 哈哈
  17. CleanMyMac XMac一键清理工具功能详解
  18. 地铁自助售票机模拟系统-C++课程设计
  19. 区块链的架构是如何定义的?
  20. 使用网页源代码下载网络录播/回放/缓存视频

热门文章

  1. 《数学之美》——第九章 个人笔记
  2. C语言基础知识:checksum += (0x000000FF) *a++;    以及 *( (unsigned int *)a ) = checksum;  的理解
  3. 易语言软件加VMProtect壳的正确方法
  4. 软件测试那些事儿(持续更新中)
  5. 基于javaweb+JSP+Servlet简单购物车
  6. 精准营销服务平台设计-基于大数据和AI的商业智能平台
  7. 数据结构__图书管理系统(C语言)
  8. 高斯羽烟gis应用java实现模型计算
  9. 《HTTP权威指南》第一章学习总结
  10. EBS中 EXCEL 格式报表输出的公用API