轮转调度算法(RR算法)
-
基本思想:
系统将所有的就绪进程按FCFS策略排成一个就绪队列。系统可设置每隔一定时间(如30ms)便产生一次中断,去激活进程调度程序进行调度,把CPU分配给队首进程,并令其执行一个时间片。当它运行完毕后,将进程管道就绪队列的队尾,再把处理机分配给就绪队列中新的队首进程,也让它执行一个时间片,以此类推。这样,就可以保证就绪队列中的所有进程在确定的时间段内,都能获得一个时间片的处理机时间。 -
实现方法:
将进程按FCFS排成一个队列,每次调度取队首进程分配CPU,时间片到,将PCB挂到就绪队尾。 -
进程切换时机
在时间片轮转调度算法中,应在何时进行进程的切换,可分为两种情况:
① 若一个时间片尚未用完,正在运行的进程便已经完成,就立即激活调度程序,将它从就绪队列中删除,再调度就绪队列中队首的进程运行,并启动一个新的时间片。
② 在一个时间片用完时,计时器中断处理程序被激活。如果进程尚未运行完毕,调度程序将把它送往就绪队列的末尾。 -
时间片大小的确定
在轮转算法中,时间片的大小对系统性能有很大的影响。图1-1示出了时间片分别为q=1和q=4时对平均周转时间的影响。
简单分析一下上图的算法:
当时间片为1的请况下,进程A首先到达开始占据cpu运行,当时间片用完后。进程B到达进程B开始占用cpu运行对应一个时间片的时间,依次类推就可算出最后每个进程的完成时间,知道完成时间后,就可算出周转时间和带权周转时间。
周转时间 =完成时间-到达时间
带权周转时间 = 周转时间/到达时间
还有需要注意这种情况:
时间片:2
进程 | A | B | C | D |
---|---|---|---|---|
到达时间 | 0 | 2 | 5 | 9 |
运行时间 | 4 | 4 | 4 | 4 |
周转时间 | 6 | 6 | 9 | 7 |
平均周转时间 | 1.50 | 1.50 | 2.25 | 1.75 |
运行过程:
A运行2,B运行2,C未到达,又运行A2,A结束,此时C已到达,但在队尾,还是运行B2,B结束,现在运行C2,此时D已到达,所以运行D2,再运行C2,最后运行D2,
可以计算出:
A结束是6,周转为6(6-0),
B结束是8,周转也是6(8-2),
C结束是14,周转9(14-5),
D结束是16,周转是7(16-9),
平均周转时间=(6+6+9+7)/4=7,
加权平均周转时间=(6/4+6/4+7/4+9/4)/4=1.75
新到达的总是在队尾,B第一次运行完,C未到达,只能返回队首运行A,A运行完,又运行B,此时C虽然到达,但是在队尾(B之后)。注意队列机制,就容易理解了。
C语言代码实现
说明:为了简化程序,程序中并未使用队列实现,而是通过数组模拟队列的形式进行实现的。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define TAKEIN "takein" //对应进程的状态
#define WAIT "wait"
#define RUN "run"
#define FINISH "finish"
#define PNUMBER 5 //进程数量
#define TRUE 1
#define FALSE 0
typedef struct pcd //进程结构体
{
char processName[20]; //进程名称
int arriveTime; //进程到达时间
int startTime; //进程开始时间
int endTime; //进程结束时间
int runTime; //进程运行时间大小
int turnOverTime; //周转时间
float userweightTurnOverTime;//带权周转时间
char provessStatus[10]; //进程状态
int runTimeed; //进程已经运行的时间
int bz; //第一次运行标志位
} pcd;
pcd pcds[PNUMBER]; //进程数组
int currentTime = 0; //当前时间
int processIndex = 0; //进程编号
int cpuTime = 4; //时间片大小
int size = PNUMBER;