情况介绍

基本原理

  1. 系统将所有就绪进程按照FCFS的原则,排成一个队列依次调度。
  2. 把CPU分配给队首进程,执行一个时间片(10-100ms)。
  3. 时间片用完后,系统计时器发出时钟中断,该进程将被剥夺CPU并插入就绪队列末尾。

切换时机

  1. 若时间片没有用完,进程就结束,那么立即调度就绪队列中的队首进程运行,并启动一个新的时间片。
  2. 如果在一个时间片用完时,进程尚未运行完毕,则剥夺CPU,调度程序把它送往队列的末尾。

参数公式

周转时间=作业完成时刻-作业到达时刻;

带权周转时间=周转时间/服务时间;

平均周转时间=作业周转总时间/作业个数;

平均带权周转时间=带权周转总时间/作业个数。

注意事项

  1. 时间片结束的时候,如果有新进程到来,先进队列,再将当前移到队尾
  2. 新进程进队列有两种方式,一种是进队列的队尾,一种是进队列的队首。

书上的表格是使用新进程放队首的效果,注意红框的带权周转时间应该算错了,E的带权周转时间应为3.25

模拟草稿

进程执行情况:

队列执行情况:

具体实现

将新进程放在队列的队尾

C++代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
struct PCB {int id;             //进程编号 char name;           //进程名字int arrive;           //到达时间int serve;            //服务时间int finish;           //完成时刻//排序优先参考到达时间,其次是服务时间 bool operator< (const PCB &t) const{if(arrive != t.arrive) return arrive < t.arrive;return serve < t.serve;};
};
const int N = 10;  //最多10个进程
const int M = 100; //最长100个时间单位
PCB pcb_list[N];    //进程列表
vector<PCB> table[M]; //进程时刻表
queue<PCB> que;       //进程队列
int n,t,q,sjp;  //进程数,总计时,固定时间片,运转时间片
int max_time;   //最大时间
void query() {  //查询当前是否有进程到达,有则入队//将当前时刻的所有进程入队for(int i = 0; i < table[t].size(); i++)que.push(table[t][i]);
}
void run() {cout << "当前时刻\t" << "运行进程\t" << "剩余服务时间" << endl;PCB cur = pcb_list[0];  //初始化当前进程sjp = q;  //初始化时间片 for(t = 0; t <= max_time; t++) {    //跑时间 query();  //当前是否有进程到达,有则入队if(que.empty()) continue;    //如果队列空,跳过if(!sjp || !cur.serve) {   //时间片用完了 或 当前进程运行完了,则调度 sjp = q;    //恢复时间片que.pop();   //队首出队if(cur.serve) que.push(cur);  //如果当前进程没有运行完,则移到队尾else pcb_list[cur.id].finish = t;    //运行完了,设置完成时刻 if(!que.empty()) cur = que.front();   //取新的队首else continue;   //已经空了,跳过 }cout << t << "\t\t" << cur.name << "\t\t" << cur.serve << endl;   //输出当前时刻状态 sjp--,cur.serve--;   //时间片-1,当前进程服务时间-1 }
}
void set_max_time() {for(int i = 0; i < n; i++)max_time += pcb_list[i].serve;max_time+=5;//多加一点避免边界问题(删掉也没关系,程序已经很完备了)
}
int main() {printf("时间片轮转调度算法\n\n");printf("请输入进程数 时间片\n");cin >> n >> q;   //输入进程数和时间片时长printf("请输入每个进程的进程名 到达时间 服务时间\n");for(int i = 0; i < n; i++)cin >> pcb_list[i].name >> pcb_list[i].arrive >> pcb_list[i].serve;sort(pcb_list,pcb_list+n);   //对进程按到达时间排序for(int i = 0; i < n; i++) {pcb_list[i].id = i;  //给进程编号 table[pcb_list[i].arrive].push_back(pcb_list[i]);   //将进程送到时刻表 }set_max_time(); //设置最大运行时间run();    //开始运行cout << "进程名字\t" << "完成时间\t" << "周转时间\t" << "带权周转时间" << endl;for(int i = 0; i < n; i++) {int zzsj = pcb_list[i].finish-pcb_list[i].arrive;double dqzzsj = (double)zzsj / pcb_list[i].serve;printf("%c\t\t%d\t\t%d\t\t%.2lf\n",pcb_list[i].name,pcb_list[i].finish,zzsj,dqzzsj);}return 0;
}

说明:

  1. 如果不用table来记录每个时间点上的新进程,也可以query的时候遍历一遍pcb_list。

时间片为1的时候

运行效果:

与草稿纸上模拟的一致

时间片为4的时候

运行效果:

与草稿纸上模拟的一致

将新进程放在队列的队首

C++代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
using namespace std;
struct PCB {int id;             //进程编号 char name;           //进程名字int arrive;           //到达时间int serve;            //服务时间int finish;           //完成时刻//排序优先参考到达时间,其次是服务时间 bool operator< (const PCB &t) const{if(arrive != t.arrive) return arrive < t.arrive;return serve < t.serve;};
};
const int N = 10;  //最多10个进程
const int M = 100; //最长100个时间单位
PCB pcb_list[N];    //进程列表
vector<PCB> table[M]; //进程时刻表
deque<PCB> que;       //进程队列
int n,t,q,sjp;  //进程数,总计时,固定时间片,运转时间片
int max_time;   //最大时间
void query() {  //查询当前是否有进程到达,有则入队//将当前时刻的所有进程入队for(int i = 0; i < table[t].size(); i++)que.push_front(table[t][i]);
}
void run() {cout << "当前时刻\t" << "运行进程\t" << "剩余服务时间" << endl;PCB cur = pcb_list[0];  //初始化当前进程sjp = q;  //初始化时间片 for(t = 0; t <= max_time; t++) {    //跑时间//记录队列中队首的进程deque<PCB>::iterator it;it = que.begin();query();   //当前是否有进程到达,有则入队if(que.empty()) continue;    //如果队列空,跳过if(!sjp || !cur.serve) {   //时间片用完了 或 当前进程运行完了,则调度 sjp = q;    //恢复时间片que.erase(it);   //删除之前记录的进程(相当于把那个进程出队) if(cur.serve) que.push_back(cur); //如果当前进程没有运行完,则移到队尾else pcb_list[cur.id].finish = t;    //运行完了,设置完成时刻 if(!que.empty()) cur = que.front();   //取新的队首else continue;   //已经空了,跳过 }cout << t << "\t\t" << cur.name << "\t\t" << cur.serve << endl;   //输出当前时刻状态 sjp--,cur.serve--;   //时间片-1,当前进程服务时间-1 }
}
void set_max_time() {for(int i = 0; i < n; i++) {max_time += pcb_list[i].serve;}max_time+=5;//多加一点避免边界问题(删掉也没关系,程序已经很完备了)
}
int main() {printf("时间片轮转调度算法\n\n");printf("请输入进程数 时间片\n");cin >> n >> q;   //输入进程数和时间片时长printf("请输入每个进程的进程名 到达时间 服务时间\n");for(int i = 0; i < n; i++)cin >> pcb_list[i].name >> pcb_list[i].arrive >> pcb_list[i].serve;sort(pcb_list,pcb_list+n);   //对进程按到达时间排序for(int i = 0; i < n; i++) {pcb_list[i].id = i;  //给进程编号 table[pcb_list[i].arrive].push_back(pcb_list[i]);   //将进程送到时刻表 }set_max_time(); //设置最大运行时间run();    //开始运行cout << "进程名字\t" << "完成时间\t" << "周转时间\t" << "带权周转时间" << endl;for(int i = 0; i < n; i++) {int zzsj = pcb_list[i].finish-pcb_list[i].arrive;double dqzzsj = (double)zzsj / pcb_list[i].serve;printf("%c\t\t%d\t\t%d\t\t%.2lf\n",pcb_list[i].name,pcb_list[i].finish,zzsj,dqzzsj);}return 0;
}

说明:

  1. 由于新进程要放在队首,所以要用双向队列的容器deque。
  2. 由于新进程放在队首,所以原队首容易找不到,所以要用迭代器记录一下原来队首的进程,方便把它出队。

时间片为1的时候

运行效果:

与草稿纸上模拟一致

时间片为4的时候,放队首和队尾的效果是一样的,就不重复展示了。

操作系统实验二——时间片轮转调度算法(RR算法)(新进程放队首和队尾两种C++实现)相关推荐

  1. 操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)

    实验二 进程调度 一.     实验目的 1.       理解进程运行的并发性. 2.       理解处理器的三级调度. 3.       掌握先来先服务的进程调度算法. 4.       掌握短 ...

  2. 操作系统实验二——进程调度算法(FCFS、RR)

    目录 进程调度算法 FCFS算法代码 RR算法代码 进程调度算法 FCFS算法代码 #include <stdio.h> #include <string.h> #includ ...

  3. 广州大学2020操作系统实验二:银行家算法

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

  4. 操作系统实验二:物理内存管理系统

    操作系统实验二:物理内存管理系统 一. 实验目的 二. 实验内容 三. 实验准备 [实验概述] [关键数据结构] [执行流程] 四. 实验步骤 (一) 练习0:填写已有实验 (二) 练习1:实现 fi ...

  5. C语言实现操作系统的进程调度算法--RR算法

    c语言实现调度算法--RR算法 测试输入为4个进程,时间片q=3,进程为A.B.C.D,序列号为都为0,运行时间分别为6/7/9/12 测试输入为4个进程,时间片q=3,进程为A.B.C.D,序列号为 ...

  6. 操作系统实验1—实现单处理机下的进程调度程序

    操作系统实验1-实现单处理机下的进程调度程序 文章目录 操作系统实验1-实现单处理机下的进程调度程序 实验描述 设计思路 上机代码 测试结果 心得体会 实验描述 实验内容: 编写一个单处理机下的进程调 ...

  7. 实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    贺邦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数 ...

  8. ML之catboost:基于自定义数据集利用catboost 算法实现回归预测(训练采用CPU和GPU两种方式)

    ML之catboost:基于自定义数据集利用catboost 算法实现回归预测(训练采用CPU和GPU两种方式) 目录 基于自定义数据集利用catboost 算法实现回归预测(训练采用CPU和GPU两 ...

  9. 操作系统|时间片轮转调度算法(RR)

    模拟实现非抢占式 将进程信息表的信息根据进入时间排序,判断当前时间线下有哪些进程到达,将其插入到等待队列中,等待分配一个时间片,若进程未全部执行结束,将其插入队尾,等待下次分配. 在进行插入队尾前判断 ...

最新文章

  1. 把Array说透(续一)
  2. 项目--教师日常办公平台中的活动图
  3. python for android 安装配置_mac appium for android 环境搭建 (appium python pycharm)
  4. JPM Coin三部曲 (上) :深入理解摩根幣的運作
  5. 5 thinkpad 黑将评测_ThinkPad L380视频评测:全能型商务助手
  6. 用注册机破解navicat12
  7. openpyxl使用教程
  8. Mac连接京瓷打印机Fs-1030MFP/DP
  9. {黑科技}哔哩哔哩视频三倍速播放
  10. oracle startup mount是什么意思,startup,startup mount,startup nomount之间的区别-Oracle
  11. 基于Android技术的物联网应用开发
  12. Stimulsoft Reports报告工具,Stimulsoft创建和构建报告
  13. AIGC席卷,抖快、阅文、知乎大战网文圈
  14. 关于517coding的10月月赛
  15. python保存不了是怎么回事_每天的微博热点保存不了怎么办?python帮你实现微博热点下载...
  16. 中兴盒子B860AV1.1-T2版刷公版固件教程
  17. 华为防火墙故障处理工具之查看路由表
  18. sct分散加载文件格式与应用
  19. 深入理解 Flink 容错机制
  20. MYSQL 存储过程的简单使用

热门文章

  1. python自动登录校园网_python实现校园网一键自动连接
  2. Win 10系统安装3ds max 2014
  3. 操作系统:临界区、临界资源的概念及相关习题
  4. 基于 Matlab的录屏软件
  5. 为什么子进程要继承处理器亲缘性?
  6. 计算机音乐创作是什么,计算机音乐创作,creation of computer music,音标,读音,翻译,英文例句,英语词典...
  7. 关于如何设置收藏本站和设为首页
  8. 【error】_smartbi数据集超出最大行数: DataRows > 1000
  9. 5分钟白嫖我常用的免费效率软件/工具!效率300% up!
  10. 人脸表情系列:论文阅读——Facial Expression Recognition by De-expression Residue Learning