文章目录

  • 进程调度(FCFS和SJF)
    • 问题描述
    • 实验环境
    • 输入
    • 输出
    • 测试数据
    • 实验设计
      • 数据结构
      • 函数的功能、参数和输出
      • 主要函数算法设计
      • 详细设计
      • 流程图
    • 实验结果与分析
      • 结果展示与描述
      • 结果分析
      • 总结
    • 源代码

进程调度(FCFS和SJF)

问题描述

设计程序模拟进程的先来先服务FCFS和短作业优先SJF调度过程。假设有n个进程分别在T1, … ,Tn时刻到达系统,它们需要的服务时间分别为S1, … ,Sn。分别采用先来先服务FCFS和短作业优先SJF进程调度算法进行调度,计算每个进程的完成时间,周转时间、带权周转时间和等待时间,并且统计n个进程的平均周转时间、平均带权周转时间和平均等待时间。最后,对两个算法做出比较评价。

要求采用先来先服务FCFS和短作业优先SJF分别调度进程运行,计算每个进程的周转时间,带权周转时间和等待时间,并且计算所有进程的平均周转时间,带权平均周转时间和平均等待时间。

实验环境

  • Windows 11
  • Visual Studio Code
  • gcc version 8.1.0

输入

进程数n,进程编号,以及每个进程的到达时间T1, … ,Tn和服务时间S1, … ,Sn。在屏幕上要以表的形式显示输入的信息。

根据显示信息:“1-FCFS,2-SJF”,选择1或者2进入对应的算法过程。

输出

  • 要求模拟整个调度过程,输出每个时刻的进程运行状态
  • 要求输出计算出来的每个进程的周转时间,带权周转时间和等待时间
  • 要求输出所有进程的平均周转时间,带权平均周转时间和平均等待时间

测试数据

Process Num. 1 2 3 4 5
Arrival Time 0 1 3 4 6
CPU Burst 5 7 3 8 2

实验设计

数据结构

#define MaxNum 100                                // 最大进程数
double AverageWT_FCFS = 0, AverageWT_SJF = 0;     // 平均等待时间
double AverageTAT_FCFS = 0, AverageTAT_SJF = 0;   // 平均周转时间
double AverageWTAT_FCFS = 0, AverageWTAT_SJF = 0; // 平均带权周转时间
using namespace std;// 进程结构体
typedef struct PROCESS
{int index;                    // 进程序号double ServiceTime;           // 服务时间double ArrivalTime;           // 到达时间double StartTime;             // 开始时间double FinishTime;            // 结束时间double TurnArroundTime;       // 周转时间double WaitTime;              // 等待时间double WeightTurnArroundTime; // 带权周转时间
} PRO[MaxNum];

函数的功能、参数和输出

// 输出各进程的到达时间和服务时间
void display_base(PRO PC, int n)// 输出每个时刻的进程运行状态
void display_status(PRO PC, int n)// 输出各进程的周转时间、带权周转时间和等待时间
void display_time(PRO PC, int n)// 输出所有进程的的平均周转时间、带权平均周转时间和平均等待时间
void display_average()// 按到达时间排序
void SortArrival(PRO &PC, int n)// 计算各项时间 z为记号变量 用于区别FCFS和SJF
void CountTime(PRO &PC, int n, int z)// FCFS算法
void FCFS(PRO &PC, int n)// SJF算法
void SJF(PRO &PC, int n)// 关于以上函数的参数,PC均为进程的结构体数组,n均为进程的数量

主要函数算法设计

// 模拟整个调度过程,输出每个时刻的进程运行状态
void display_status(PRO PC, int n)
{cout << endl;cout << "Process Num\t"<< "Start Time\t"<< "End Time\t"<< "Ready Queue" << endl;for (int t = 0; t < n; t++) // 循环输出每个进程的服务时间内 处在等待队列的进程 即到达时间在当前进程开始和结束时间之间的进程{cout << PC[t].index << "\t\t" << PC[t].StartTime << "\t\t" << PC[t].FinishTime << "\t\t";for (int q = t + 1; q < n; q++){if (PC[q].ArrivalTime <= PC[t].FinishTime)cout << PC[q].index << " ";}cout << endl;}
}
// 按到达时间排序
void SortArrival(PRO &PC, int n)
{PROCESS temp;for (int i = 0; i < n; i++){int min = i;for (int j = i + 1; j < n; j++)if (PC[j].ArrivalTime < PC[min].ArrivalTime)min = j;temp = PC[i];PC[i] = PC[min];PC[min] = temp;}
}
// 计算各项时间 z为记号变量 用于区别FCFS和SJF
void CountTime(PRO &PC, int n, int z)
{PC[0].StartTime = PC[0].ArrivalTime;PC[0].FinishTime = PC[0].ArrivalTime + PC[0].ServiceTime;PC[0].TurnArroundTime = PC[0].FinishTime - PC[0].ArrivalTime;PC[0].WaitTime = 0;PC[0].WeightTurnArroundTime = PC[0].TurnArroundTime / PC[0].ServiceTime;double sumWT = PC[0].WaitTime, sumTAT = PC[0].TurnArroundTime, sumWTAT = PC[0].WeightTurnArroundTime;for (int m = 1; m < n; m++){if (PC[m].ArrivalTime >= PC[m - 1].FinishTime){PC[m].StartTime = PC[m].ArrivalTime;PC[m].WaitTime = 0;}else{PC[m].StartTime = PC[m - 1].FinishTime;PC[m].WaitTime = PC[m - 1].FinishTime - PC[m].ArrivalTime;}PC[m].FinishTime = PC[m].StartTime + PC[m].ServiceTime;PC[m].TurnArroundTime = PC[m].FinishTime - PC[m].ArrivalTime;PC[m].WeightTurnArroundTime = PC[m].TurnArroundTime / PC[m].ServiceTime;sumWT += PC[m].WaitTime;sumTAT += PC[m].TurnArroundTime;sumWTAT += PC[m].WeightTurnArroundTime;}if(z == 1) // 计算FCFS{AverageWT_FCFS = sumWT / n;AverageTAT_FCFS = sumTAT / n;AverageWTAT_FCFS = sumWTAT / n;}if(z == 2) // 计算SJF{AverageWT_SJF = sumWT / n;AverageTAT_SJF = sumTAT / n;AverageWTAT_SJF = sumWTAT / n;}
}
// FCFS算法
void FCFS(PRO &PC, int n)
{SortArrival(PC, n);    // 按到达时间进行排序CountTime(PC, n, 1);   // 计算各项时间display_status(PC, n); // 模拟整个调度过程,输出每个时刻的进程运行状态display_time(PC, n);   // 输出各进程的周转时间、带权周转时间和等待时间
}
// SJF算法
void SJF(PRO &PC, int n)
{SortArrival(PC, n); // 先按到达时间进行排序// 类比选择排序的思想 从第二个到达的进程开始 遍历当前进程后面的进程 如果有服务时间比当前最短服务时间更短的 则交换位置int End = PC[0].ArrivalTime + PC[0].ServiceTime; // 之前服务的结束时间int tmin = 1;                                    // 当前最短服务时间的索引PROCESS temp;for (int x = 1; x < n; x++){for (int y = x + 1; y < n; y++){if (PC[y].ArrivalTime <= End && PC[y].ServiceTime < PC[tmin].ServiceTime)tmin = y;}// 将当前进程与等待队列中服务时间最短的进程进行交换temp = PC[x];PC[x] = PC[tmin];PC[tmin] = temp;End += PC[x].ServiceTime;}CountTime(PC, n, 2);   // 计算各项时间display_status(PC, n); // 模拟整个调度过程,输出每个时刻的进程运行状态display_time(PC, n);   // 输出各进程的周转时间、带权周转时间和等待时间
}

详细设计

  • 变量初始化

  • 接收用户输入n,T1, … ,Tn,S1, … ,Sn

  • 循环等待用户选择算法:1-FCFS,2-SJF

  • 按照选择算法进行进程调度

  • 计算进程的开始时间、完成时间、周转时间、带权周转时间和等待时间

  • 计算所有进程的平均周转时间、平均带权周转时间和平均等待时间

  • 按格式输出调度结果

流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ftLBFZYW-1657501806383)(E:\work\操作系统\实验2\code\flow.png)]

实验结果与分析

结果展示与描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AGXUoPej-1657501806385)(E:\work\操作系统\实验2\code\result.png)]

  • 输入进程数量和各进程的基本信息:到达时间和服务时间
  • 选择算法 注:在选择0之前需要将1和2都选择过
  • 选择1 按FCFS算法输出各进程的执行顺序、开始和完成时间、等待队列、周转时间、带权周转时间和等待时间
  • 选择2 按SJF算法输出各进程的执行顺序、开始和完成时间、等待队列、周转时间、带权周转时间和等待时间
  • 选择0 输出本实验数据使用两种算法得到的不同平均周转时间、平均带权周转时间和平均等待时间
  • 实验结束

结果分析

  • FCFS算法通过按到达时间排序的方式得到服务顺序,计算时还需要考虑当前进程结束时下一个进程是否已经到达,进行条件判断后代入不同结果计算,最终验证与手动计算结果相同
  • SJF算法先按到达时间排序,再将每个进程服务时间段内的等待队列按服务时间由短至长排序,从而得到服务顺序,之后的计算方式与FCFS相同,最终验证与手动计算结果相同

总结

  • 本次实验将所有需要重复使用的代码都打包成函数,在主函数中直接进行调用,使代码简洁、清晰。

  • 在数据结构方面,因为对队列的使用还不是很熟悉,所以我在实现算法的过程中,使用了结构体数组,考虑到计算过程会出现整数与小数的混合运算,我将除进程序号外的所有数据都设为double型,便不会在结果中出现小数部分被舍弃的问题。

  • 对于SJF算法的排序,我直接对等待队列进行排序,避免使用复杂的算法,使用变量End判定进程是否处在等待队列,将所有进程都排好序之后直接调用CountTime函数进行计算,不仅使算法更简单,还体现出了FCFS和SJF两种算法的区别,便于学习和理解。

  • 在主函数中,使用while循环,重复选择算法,若选择0则输出所有进程的平均周转时间,带权平均周转时间和平均等待时间并且退出循环,以实现循环选择算法的功能。

源代码

#include <iostream>#define MaxNum 100                                // 最大进程数
double AverageWT_FCFS = 0, AverageWT_SJF = 0;     // 平均等待时间
double AverageTAT_FCFS = 0, AverageTAT_SJF = 0;   // 平均周转时间
double AverageWTAT_FCFS = 0, AverageWTAT_SJF = 0; // 平均带权周转时间
using namespace std;// 进程结构体
typedef struct PROCESS
{int index;                    // 进程序号double ServiceTime;           // 服务时间double ArrivalTime;           // 到达时间double StartTime;             // 开始时间double FinishTime;            // 结束时间double TurnArroundTime;       // 周转时间double WaitTime;              // 等待时间double WeightTurnArroundTime; // 带权周转时间
} PRO[MaxNum];// 输出各进程的到达时间和服务时间
void display_base(PRO PC, int n)
{cout << endl;cout << "Process Num\t"<< "Arrival Time\t"<< "CPU Burst" << endl;for (int t = 0; t < n; t++)cout << PC[t].index << "\t\t" << PC[t].ArrivalTime << "\t\t" << PC[t].ServiceTime << endl;
}// 模拟整个调度过程,输出每个时刻的进程运行状态
void display_status(PRO PC, int n)
{cout << endl;cout << "Process Num\t"<< "Start Time\t"<< "End Time\t"<< "Ready Queue" << endl;for (int t = 0; t < n; t++) // 循环输出每个进程的服务时间内 处在等待队列的进程 即到达时间在当前进程开始和结束时间之间的进程{cout << PC[t].index << "\t\t" << PC[t].StartTime << "\t\t" << PC[t].FinishTime << "\t\t";for (int q = t + 1; q < n; q++){if (PC[q].ArrivalTime <= PC[t].FinishTime)cout << PC[q].index << " ";}cout << endl;}
}// 输出各进程的周转时间、带权周转时间和等待时间
void display_time(PRO PC, int n)
{cout << endl;cout << "Process Num\t"<< "Turnaround Time\t"<< "Weighted Turnaround Time\t"<< "Waiting Time" << endl;for (int t = 0; t < n; t++)cout << PC[t].index << "\t\t" << PC[t].TurnArroundTime << "\t\t" << PC[t].WeightTurnArroundTime << "\t\t\t\t" << PC[t].WaitTime << endl;
}// 输出所有进程的的平均周转时间、带权平均周转时间和平均等待时间
void display_average()
{cout << endl;cout << "Algorithm\t"<< "Average TAT\t"<< "Average WTAT\t"<< "Average WT" << endl;cout << "FCFS\t\t" << AverageTAT_FCFS << "\t\t" << AverageWTAT_FCFS << "\t\t" << AverageWT_FCFS << endl;cout << "SJF\t\t" << AverageTAT_SJF << "\t\t" << AverageWTAT_SJF << "\t\t" << AverageWT_SJF << endl;
}// 按到达时间排序
void SortArrival(PRO &PC, int n)
{PROCESS temp;for (int i = 0; i < n; i++){int min = i;for (int j = i + 1; j < n; j++)if (PC[j].ArrivalTime < PC[min].ArrivalTime)min = j;temp = PC[i];PC[i] = PC[min];PC[min] = temp;}
}// 计算各项时间 z为记号变量 用于区别FCFS和SJF
void CountTime(PRO &PC, int n, int z)
{PC[0].StartTime = PC[0].ArrivalTime;PC[0].FinishTime = PC[0].ArrivalTime + PC[0].ServiceTime;PC[0].TurnArroundTime = PC[0].FinishTime - PC[0].ArrivalTime;PC[0].WaitTime = 0;PC[0].WeightTurnArroundTime = PC[0].TurnArroundTime / PC[0].ServiceTime;double sumWT = PC[0].WaitTime, sumTAT = PC[0].TurnArroundTime, sumWTAT = PC[0].WeightTurnArroundTime;for (int m = 1; m < n; m++){if (PC[m].ArrivalTime >= PC[m - 1].FinishTime){PC[m].StartTime = PC[m].ArrivalTime;PC[m].WaitTime = 0;}else{PC[m].StartTime = PC[m - 1].FinishTime;PC[m].WaitTime = PC[m - 1].FinishTime - PC[m].ArrivalTime;}PC[m].FinishTime = PC[m].StartTime + PC[m].ServiceTime;PC[m].TurnArroundTime = PC[m].FinishTime - PC[m].ArrivalTime;PC[m].WeightTurnArroundTime = PC[m].TurnArroundTime / PC[m].ServiceTime;sumWT += PC[m].WaitTime;sumTAT += PC[m].TurnArroundTime;sumWTAT += PC[m].WeightTurnArroundTime;}if (z == 1) // 计算FCFS{AverageWT_FCFS = sumWT / n;AverageTAT_FCFS = sumTAT / n;AverageWTAT_FCFS = sumWTAT / n;}if (z == 2) // 计算SJF{AverageWT_SJF = sumWT / n;AverageTAT_SJF = sumTAT / n;AverageWTAT_SJF = sumWTAT / n;}
}// FCFS算法
void FCFS(PRO &PC, int n)
{SortArrival(PC, n);    // 按到达时间进行排序CountTime(PC, n, 1);   // 计算各项时间display_status(PC, n); // 模拟整个调度过程,输出每个时刻的进程运行状态display_time(PC, n);   // 输出各进程的周转时间、带权周转时间和等待时间
}// SJF算法
void SJF(PRO &PC, int n)
{SortArrival(PC, n); // 先按到达时间进行排序// 类比选择排序的思想 从第二个到达的进程开始 遍历当前进程后面的进程 如果有服务时间比当前最短服务时间更短的 则交换位置int End = PC[0].ArrivalTime + PC[0].ServiceTime; // 之前服务的结束时间int tmin = 1;                                    // 当前最短服务时间的索引PROCESS temp;for (int x = 1; x < n; x++){for (int y = x + 1; y < n; y++){if (PC[y].ArrivalTime <= End && PC[y].ServiceTime < PC[tmin].ServiceTime)tmin = y;}// 将当前进程与等待队列中服务时间最短的进程进行交换temp = PC[x];PC[x] = PC[tmin];PC[tmin] = temp;End += PC[x].ServiceTime;}CountTime(PC, n, 2);   // 计算各项时间display_status(PC, n); // 模拟整个调度过程,输出每个时刻的进程运行状态display_time(PC, n);   // 输出各进程的周转时间、带权周转时间和等待时间
}int main()
{PRO pc;int n;cout << "请输入进程的数量:";cin >> n;cout << "请输入每个进程的到达时间和服务时间:" << endl;for (int i = 0; i < n; i++){pc[i].index = i + 1;cin >> pc[i].ArrivalTime >> pc[i].ServiceTime;}display_base(pc, n);int choice;cout << endl<< "输入0-输出平均时间并退出程序  输入1-FCFS  输入2-SJF" << endl<< "请选择要执行的操作:";cin >> choice;while (choice != 0){if (choice == 1)FCFS(pc, n);if (choice == 2)SJF(pc, n);cout << endl<< "请输入接下来要执行的操作:";cin >> choice;}display_average();cout << endl;system("pause");return 0;
}

操作系统-进程调度(FCFS和SJF)相关推荐

  1. 操作系统进程调度 FCFS,SJF,RR算法(Java实现)

    有用就给个关注呗 进程控制块 为了管理和控制进程,系统在创建每一个进程时,都为其开辟一个专用的存储区,用以随时记录它在系统中的动态特性.通常,把这一存储区称为该进程的"进程控制块" ...

  2. 进程调度----FCFS,SJF,优先级调度,RR

    1,FCFS 先服务先调度 FCFS策略可以通过FIFO队列容易的实现.当一个进程进入就绪队列时,它的PCB会被连接到队列尾部.当CPU空闲时,它会分配给位于队列头部的进程,并且这个运行进程从队列中移 ...

  3. 操作系统中的调度算法FCFS、SJF、RR算法(Java实现)

    Proce类: package five; public class Process { public String name;// 进程名称 public int arrivalTime;// 到达 ...

  4. 进程调度java实现(FCFS,SJF,HRRN,RR)

    进程JCB类实现 我们设置了一系列描述进程的参数,并提供一个构造函数用于初始化进程. public class JCB {String name;//进程名int arriveTime;//到达时间i ...

  5. 操作系统进程调度算法(FCFS、SJF、高响应比)

    进程调度算法(FCFS.SJF.高响应比) 一.算法描述 1.先来先服务(FCFS)调度算法 (1)FCFS是最简单的调度算法,该算法可用于作业调度,也可用于进程调度. (2)算法规则:系统按照作业到 ...

  6. c语言实现FCFS SJF算法,实现FCFS和SJF调度算法.docx

    操作系统实验报告 实验一:作业调度 学院: 软件学院 专业: 软件工程 班级: 软件工程12-01 姓名: *** 学号:541213460157 实验一:作业调度 实现FCFS和SJF调度算法 [实 ...

  7. 进程分配算法(FCFS,SJF,RR)

    一.进程调度算法的背景 在多道程序环境下,内存中存在着多个进程,其数目往往多于处理机数目.这就要求系统能按某种算法,动态地将处理机分配给处于就绪状态的一个进程,使之执行.分配处理机的任务是由处理机调度 ...

  8. FCFS,SJF,HRRN调度算法

    FCFS,SJF,HRRN调度算法 各种调度算法的学习思路 算法思想 算法规划 这种调度算法是用于作业调度还是进程调度 抢占式?非抢占式? 优缺点 是否会导致饥饿(某进程/作业长期得不到服务) 先来先 ...

  9. OS2.2.4:FCFS、SJF、HRRN调度算法

    文章目录 知识总览 几个需要思考的问题 调度算法 先来先服务(FCFS) 实例 小结 短作业优先 非抢占式短作业优先(SJF) 实例 抢占式最短剩余时间优先(SRTN) 实例 小细节 小结 FCFS与 ...

最新文章

  1. redhat 6.0 Enterprise企业版如何使用yum安装软件
  2. 从京东裸辞 2 年后,我的一些改变
  3. MATLAB实现牛顿插值的源程序
  4. oracle var/tmp,关于/var/tmp/.oracle 目录(ZT)
  5. SAP Spartacus login 超链接和 login form 的区别
  6. 关于Android手机CPU不同架构的问题
  7. codeforces 111A/112C Petya and Inequiations
  8. oracle 增加列 生效,oracle基础(表的创建,插入,修改,增加,列的问题)
  9. 中国团队入选美国物理学会2018年度国际物理学十大进展
  10. XFire+spring 发布webservice 及其客户端调用程序
  11. 领域的初学者--推荐的一本书
  12. TOM小游戏《大球吃小球》评测报告
  13. 1. VS2017社区版安装
  14. 蠕虫病毒html,蠕虫病毒的防治
  15. 服务器防御DDoS的方法,一文解决DDoS攻击
  16. 怎么登录163邮箱?TOMvip邮箱登录详情介绍
  17. cf(穿越火线)进游戏乱码问题解决方案
  18. 转载:在阿里工作四个月经历的总结
  19. CJBorderView 一种iOS开发中常用的虚线边框View------* An easy way to init a view with dotted line border
  20. 罗技 连点 脚本_罗技发布无线版的Pro X游戏耳机,拥有20小时续航时间

热门文章

  1. Cadence (Allegro) 转 Altium Designer
  2. python二手房使用教程_Python爬虫入门教程03:二手房数据爬取
  3. windows下利用mklink创建软链接
  4. 系统时间显示到秒-Windows10
  5. 保养腰椎,不妨做做腰肌操。
  6. Linux总线之I2C
  7. 【电气专业知识问答】问:断路器合上后即跳闸如何判别和处理?
  8. python getopterror_python getopt
  9. WPS强占8080端口
  10. 硬件检测新锐:Z武器