课程:操作系统

原算法:轮转调度算法

改进后算法:基于时间片延长的轮转调度算法

一、算法原理

1.1算法介绍


轮转Round Robin调度算法(RR,时间片调度):每次给就绪队列队首进程分配一定额度的CPU时间(时间片)执行;时间片到期时让出CPU,将运行进程排到就绪队列尾部,等候下一轮调度。

进程是平等的,按照先来先服务的次序轮流的运行一个时间片。

先来先服务+时间片抢占式

时间片结束之前,进程进入阻塞态;等待事件发生后,重新加到就绪队列的尾部; 可防止计算密集型进程过长占用处理器,而使得要使用I/O设备的进程没有机会去执行I/O操作。

1.2条件假设


前提条件:

1、默认新到达的进程先进入就绪队列

2、新进程进入队列时采用从队首进入

1.3基本原理

基本原理

系统将所有就绪进程按照条件假设,排成一个队列依次调度;

把CPU分配给队首进程,执行一个时间片(10-100ms);

时间片用完后,系统计时器发出时钟中断,该进程将被剥夺CPU并插入就绪队列末尾。

进程切换时机

1.若一个时间片尚未用完

正在运行的进程便已经完成,就立即激活调度程序,将它从就绪队列中删除,再调度就绪队列中队首的进程运行,并启动一个新的时间片。

2.若一个时间片用完时

计时器中断处理程序被激活。如果进程尚未运行完毕,调度程序就把它送往就绪队列的末尾。

时间片大小的确定

——进程切换需要消耗CPU时间: 保存、恢复寄存器和虚拟内存的映射参数;更新内核PCB等数据、链表;刷新加载内存缓冲区cache等。

时间片太小

有利于短作业,因为它能在该时间片内完成。但会频繁执行进程调度和进程上下文切换,进而增加系统的开销。 例如:时间片长4ms,进程切换需要1ms,有20%CPU时间浪费。

时间片太大

为使每个进程都能在一个时间片内完成,RR算法将退化为FCFS算法,无法满足短作业和交互式用户的需求。 例如:就绪队列中又10个进程,每个时间片100ms,那么新进入就绪态进程最长需要1s时间才能执行。

一个较为可取的时间片大小是略大于一次典型的交互所需要的时间,使大多数交互式进程能在一个时间片内完成,从而可以获得很小的响应时间。

1.4程序展示

例题:

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include <stdlib.h>
#include <conio.h>
#define getpch(type) (type*)malloc(sizeof(type)) //快速malloc
#define NULL 0
#define q 2 //时间片
/*
待实现:
PCB必须按顺序输入,到达时间从小到大。思路:1、新建标志变量,是否到达状态2、处理就绪队列,队列内有有效PCB和无效PCB(还未到达)3、处理完队头(有效PCB就绪队列的对头元素)元素后,在插入就绪队列,插入到有效PCB就绪队列的尾部4、结束条件:必须是就绪队列内没有PCB5、时间计算:除了-到达时间外,还需要考虑CPU空闲时间(就绪队列内有效数据为null时,就是计算空闲时间的时候)问题:在一个进程运行一次时间片时,但还未结束,需要插入就绪队列。是先插入,还是先判断一些其他进程是否到达。(就绪队列顺序)这里采用:先到达,即先刷新PCB状态,在插入运行时间片结束的PCB。课本解释:当该进程的时间片耗尽或运行完毕时,系统再次将CRU分配给队首进程(或新到达的紧迫进程)。由此可保证就绪队列中的所有进程在一个确定的时间段内,都能够获得一次CPU执行。因此:正确答案应该是,新到达的进程放队首。
*/
struct pcb { /* 定义进程控制块PCB */char state;//进程状态 就绪 W(Wait)、运行R(Run)、或完成F(Finish)int Atime = 0;//到达时间,默认同一时间到达int ntime;//进程运行时间int rtime;//已用CPU时间int TF;//是否为就绪队列内的有效PCB,默认有效struct pcb* link;//新建变量:是否到达的一个状态  char name[10];//进程名
}*ready = NULL, * p;
typedef struct pcb PCB;
int h = 0;//执行时间片数
int Time = 0;//CPU运行时间 利用Time记录每个进程的完成时间   (Time-Atime) 是周转时间
float allAvgTime = 0;//累加所有进程的带权周转时间/* 当该进程的时间片耗尽或运行完毕时,将该进程插入有效就绪队列*/
void sort()
{PCB* first, * second;if (ready == NULL || ready->TF == 0) /*就绪队列为空,或者进程重新插入时,就绪队列有效PCB为0,插入队首*/{p->link = ready;ready = p;}else /*尾插 只能插入到有效PCB的后面*/{first = ready;second = first->link;while (second != NULL && second->TF == 1){first = first->link;second = second->link;}p->link = second;first->link = p;}
}/*PCB必须按顺序输入,到达时间从小到大。*/
/* 建立进程控制块函数,按顺序插入到就绪队列中*/
void input()
{int i, num;system("cls"); /*清屏*/printf("\n 请输入建立的进程数?");scanf("%d", &num);for (i = 0; i < num; i++){printf("\n 进程号No.%d:\n", i);p = getpch(PCB);//申请结构体PCB内存空间printf("\n 输入进程名:");scanf("%s", &p->name);printf("\n 输入进程到达时间:");scanf("%d", &p->Atime);printf("\n 输入进程运行时间:");scanf("%d", &p->ntime);p->link = NULL;p->state = 'w';p->rtime = 0;p->TF = 1;printf("\n");sort(); //调用sort函数,插入p进程进入ready队列}
}/*查看就绪队列中有多少进程*/
int space()
{int l = 0; PCB* pr = ready;while (pr != NULL){l++;pr = pr->link;}return(l);
}/*建立进程显示函数,用于打印当前进程*/
void disp(PCB* pr)
{printf("\n 进程名 状态 到达时间 运行时间 已运行时间 到达(0/1) \n");printf("|%s\t", pr->name);printf("|%c\t", pr->state);printf("|%d\t", pr->Atime);printf("|%d\t", pr->ntime);printf("|%d\t", pr->rtime);printf("  |%d\t", pr->TF);printf("\n");
}/* 建立进程查看函数 */
void check()
{PCB* pr;printf("\n **** 当前正在运行的进程是:%s", p->name); /*显示当前运行进程*/disp(p);//封装pr = ready;printf("\n ****当前就绪队列状态为:\n"); /*显示就绪队列状态*/while (pr != NULL){disp(pr);//调用打印pr = pr->link;}
}
/*建立进程撤消函数(进程运行结束,撤消进程)*/
void destroy()
{allAvgTime = allAvgTime + (float)(Time - p->Atime) / p->ntime;printf("\n 进程 [%s] 已完成.\n周转时间为[%d ms]\n带权周转时间为[%.2f ms]\n", p->name, Time - p->Atime, (float)(Time - p->Atime) / p->ntime);free(p);
}/*在每次调用running中的sort前,刷新PCB的状态(是否到达)*/
void flushed() {PCB* traverse, * pre;traverse = ready;pre = NULL;while (traverse != NULL && traverse->TF == 1) {//只需将未到达的PCB置为0即可if (traverse->Atime > Time) {//不应该是finish时间,应该是CPU执行时间(h*q 比CPU执行时间略大 暂时就这样吧)traverse->TF = 0;}//新到达的程序(数组)放就绪队列队头//记录(front) 记录第一个0-->1(left)  循环遍历到最后一个0->1(rigth) 记录后面链表(behind  pre->behind)  //再将ready置为(left)  pre = traverse;traverse = traverse->link;}//本程序只考虑一次改变一个PCB状态(简单)if (traverse != NULL && traverse->Atime <= Time) {traverse->TF = 1;if (pre != NULL) {pre->link = traverse->link;traverse->link = ready;ready = traverse;}}
}
/* 建立进程就绪函数(进程运行时间到,置就绪状态*/
void running()
{(p->rtime) = (p->rtime) + q;if (p->rtime >= p->ntime) {if (p->rtime == p->ntime) {Time = Time + q;}else {Time = Time + (p->ntime) % q;//未利用完时间片,完成跳出}p->state = 'F';//新建一个周转时间(同一时刻创建,所以周转时间等于完成时间) ,记录完成时间// 根据周转时间/服务时间=带权周转时间//如果刚好是时间片的整数倍,直接 当前时间片*时间片数 //如果不是整数倍 则ntime%时间片+时间片destroy(); /* 调用destroy函数*/}else{Time = Time + q;//未执行完毕p->state = 'w';//就绪sort(); /*调用sort函数,重新插入到就绪队列*/flushed();//每次都要重新判断是否有PCB到达, 到达直接插入队首.}
}void main() /*主函数*/
{int len;char ch;input();//建立PCBlen = space();flushed();//PCB状态刷新while ((len != 0) && (ready != NULL)){ch = getchar();h++;printf("\n The execute number:%d \n", h);if (ready->TF == 0) {//就绪队列内没有有效PCB//这里只需加上CPU空闲时间即可  第一个无效进程的到达时间-上一个完成进程的完成(注意是完成)时间//Time= Time+(ready->Atime - Time);Time = ready->Atime;//将第一个无效PCB改为有效PCBready->TF = 1;}else {p = ready;ready = p->link;p->link = NULL;p->state = 'R';check();running();printf("\n 按任一键继续......");ch = getchar();}}printf("\n\n 进程已经完成.\n");printf("系统的平均带权周转时间为【%.2f ms】", allAvgTime / len);ch = getchar();
}

二、算法优缺点

2.1原算法优缺点

优点:

1. CPU分配相对公平

将所有的就绪进程排成了一个就绪队列,保证了就绪队列的所有进程,在一个确定的时间段内,都能够获得一次CPU的运行。

2.平均响应时间较短

进程进入就绪队列后,其前方的所有就绪队列每个只执行一次时间片,该进程就能获得首次CPU的执行。

缺点:

1.平均等待时间较长,上下文切换较费时

就绪队列中的每一个进程每次仅仅运行一个时间片,随后必须重新排到队尾,等待进程运行完成的时间较长。

2.系统耗费在进程/线程切换上的开销比较大

每执行一次时间片,都需要执行进程调度以及进程上下文的切换,增加了系统的开销。

三、算法改进

3.1改进目的

提高操作系统性能

减少任务调度和进程切换的次数:由于轮转调度算法高频率的进程切换,系统开销增加,我们通过对时间片轮转调度调度算法中进程最后一次执行时间片分配的优化,可以减少任务调度和进程切换的次数。

减少任务实际完成时间:在轮转调度算法进程平均等待时间较长,上下文切换频繁,这无疑会增加系统开销。通过增加一定的时间片值,使得当前进程不被切换出去而连续执行完剩下的工作,减少了任务实际完成的时间。

减小系统开销:通过减少任务调度和进程调度切换的次数会降低系统开销,提升CPU的运行效率,使操作系统的性能获得一定的提高。

规定期限内完成任务

在实时操作系统中, 对于同一优先级的任务用改进后的时间片轮转算法进行调度, 具有更为的重要意义, 因为在实时系统中任务在规定的期限内不能执行完毕将可能导致灾难性的后果。

例如,用改进前的时间片轮转算法对同一优先级任务进行调度时, 当前任务可能会在仅差几个甚至一个时间片就能运行完毕时, 却被进程调度程序切换出去, 从而导致本可以在规定的期限内完成的任务最终没能在规定的期限内完成。而改进后的算法则能够避免这种可能性的发生。

3.2改进后算法原理

改进后算法是在原算法原理基础上作了如下修改: 进程在运行到即将执行完毕时, 通过增加一定的时间片值, 使得当前进程能不被调度程序切换出去而连续地执行完剩下的工作。

其原理为: 在时间片轮转调度算法中对进程最后一次执行时间片进行优化, 即当进程按时间片轮转法调度时, 如果当前进程运行还需占用的 CPU时间已不足进程分配到的时间片值的二分之一(此值可调整)时, 调度算法自动为当前进程增加一定的时间片值, 使之能继续获得CPU的使用权, 从而立即完成剩余代码的执行。

3.3解决办法

need:当前进程所需时间

completed:当前进程已运行时间

counter:当前进程的时间片值

if((need - completed) <= 1.5*counter)
{counter = counter*1.5;
}

编写函数,在该函数中,更新每个任务的时间片(counter)值时,将当前进程的已运行时间与进程需要运行的时间进行比较,若其差值不大于分配的运行时间片值的1.5倍(数值可改),则将counter增加至当前值的一半。

该方法的前提条件是:需要知道参与调度的进程所需时间。

3.4实验结果

改进前的作业情况

从甘特图中可以得出,总共切换了九次进程

改进后的作业情况

四、结果对比

4.1得出结论

改进前后的对比

通过对比可知,用改进后的轮转调度算法能够有效减少进程的实际完成时间,同时也减少了进程切换次数,从而减少了系统开销,提升了CPU的运行效率,提高了操作系统的性能。

基于时间片延长的轮转调度算法相关推荐

  1. STM32基于时间片轮询机制

    1. 基于时间片的轮询调度算法(仅局限单核CPU芯片): 利用定时器为每个任务函数设定执行时间间隔,保证使用频率高的函数多次被调用,提高单核芯片的资源利用率.如果只是简单地将A.B两个函数放在whil ...

  2. OS轮转调度算法RR的C++实现

    在分时系统中,最简单也是较常见的是基于时间片的轮转(round robin,RR)调度算法.该算法采取了非常公平的处理机分配方式,即让就绪队列中的每个进程仅运行一个时间片,如果就绪队列上有n个进程,则 ...

  3. 操作系统笔记(6):RR轮转调度算法

    这比起说是操作系统实验,不如说是一个模拟算法而已, 当然目标是为了让大家更清楚地了解RR轮转调度算法原理 原理上,书上课上都讲过,实现方式上推荐直接模拟一个队列(本来就应该是这样实现的)http:// ...

  4. 操作系统大作业 基于Linux的模拟进程调度算法 运用c++语言编程 在VMware虚拟机里 centos 亲自写亲自测试 代码 说明书

    发布文章 博文管理我的博客退出 Trash Temp 操作系统大作业 基于Linux的模拟进程调度算法 运用c++语言编程 在VMware虚拟机里 centos 亲自写亲自测试 代码 说明书 @[TO ...

  5. C语言实现NP调度算法,基于任务复制的进化调度算法.pdf

    第38卷第5期 上海交通大学学报 v乩38N1).5 May2004 2叭)1年5月 SHANGHATJIA()T()N(:UNlVERSITY J[)URNAI』()F 075504 文章编号:10 ...

  6. 通用高校排课算法研究----3.基于时间片优先级排课算法

    3 基于时间片优先级排课算法描述与分析 排课问题实质上是时间.教师.班级.教室.课程这五维关系的冲突问题,要合理的解决这个问题首先要了解排课中的一些基本原则以及排课的一些基本要求. 3.1排课中的基本 ...

  7. 基于时间片优先级排课算法描述

    在描述算法之前我们把一些概念先讲清楚.在这里我们把从行政角度分的班叫自然班,把在同一个教室上课的班叫做排课班.在大学里有些公共课是几个排课班通过多媒体来一起上的,我们把这个排课班的总和叫做公共班.班级 ...

  8. 基于时间片的轮转调度算法

    在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU 分配给队首进程,并令其执行一个时间片.时间片的大小从几ms 到几百ms.当执行的时间片用完时,由一个计 ...

  9. 基于C++实现的进程调度算法

    资源下载地址:https://download.csdn.net/download/sheziqiong/85650672 一.问题描述与分析 1.1 设计构想 程序能够完成以下操作:选择调度算法;查 ...

最新文章

  1. Linux那些事儿 之 戏说USB(28)设备的生命线(十一)
  2. jQuery最简单的表单提交方式
  3. 1. spring boot起步之Hello World【从零开始学Spring Boot】
  4. u盘锁电脑_Win10电脑无法识别U盘?这5步操作就能轻松搞定,收藏备用
  5. JFinal-layui v1.2.3 发布,极速开发企业应用系统
  6. java中intvalue_Java Byte类intValue()方法的示例
  7. 链接数据库增删改通用
  8. idea部署web项目到tomcat注意事项
  9. Xshell5 访问虚拟机Ubuntu16.04
  10. android 4.4 投屏,安卓投屏助手官方
  11. Java中 ? extends T 和 ? super T 的理解
  12. 阿里TPP图化框架技术实践 — 打造算法在线服务领域极致开发体验与性能
  13. 一种人机友好的视频压缩方案(HMFVC)
  14. 离散数学学习笔记——命题逻辑
  15. 数学词汇的英译,写文章,读文献必备
  16. php 之session 进行时
  17. 洛谷OJ:P5960 【模板】差分约束算法
  18. Tomcat下载以及环境变量配置
  19. 【剑指offer-54】20190907/03 字符流中第一个不重复的字符
  20. 高恪路由设置静态路由失效的问题另类解决方法

热门文章

  1. 语音识别 - ASR whisper
  2. 【UNR #1】火车管理
  3. 转行做产品经理,如何挑选产品经理课程?
  4. USB Camera摄像头 (UVC 与 gspca)
  5. android 微信摇一摇代码,Android实现微信摇一摇功能
  6. 常用URL分享,实用地址
  7. OpenGL入门示例8——图形平移、旋转、缩放
  8. 项目管理之如何做好项目经理
  9. Maglev: 一个快速、可靠的基于软件的网络负载均衡器(翻译)
  10. Python数据处理035:结构化数据分析工具Pandas之Pandas概览