实验2 间片轮转RR进程调度算法
1、 实验目的
通过这次实验,加深对进程概念的理解,进1步掌握进程状态的转变、进程调度的策略及对系统性能的评价方法。
2、 实验内容
问题描写:
设计程序摹拟进程的时间片轮转RR调度进程。假定有n个进程分别在T1,… ,Tn时刻到达系统,它们需要的服务时间分别为S1,… ,Sn。分别利用不同的时间片大小q,采取时间片轮转RR进程调度算法进行调度,计算每一个进程的完成时间、周转时间和带权周转时间,并且统计n个进程的平均周转时间和平均带权周转时间。
3、 程序要求:
1)进程个数n;每一个进程的到达时间T1, … ,Tn和服务时间S1, … ,Sn;输入时间片大小q。
2)时间片轮转法RR调度进程运行,计算每一个进程的周转时间和带权周转时间,并且计算所有进程的平均周转时间和带权平均周转时间;
3)输出:摹拟全部调度进程,输出每一个时刻的进程运行状态,如“时刻3:进程B开始运行”等等;
4)输出:输出计算出来的每一个进程的周转时间、带权周转时间、所有进程的平均周转时间和带权平均周转时间。
4、 需求分析
(1) 输入的情势和输入值的范围
真实进程数
各进程的到达时间
各进程的服务时间

(2) 输出的情势
摹拟全部调度进程、周转时间、带权周转时间、所有进程的平均周转时间和带权平均周转时间。
(3)测试用例
|
作业情况
时间片 |
进程名 |
A |
B |
C |
D |
E |
平均 |
|
到达时间 |
0 |
1 |
2 |
3 |
4 |
|
|
|
服务时间 |
4 |
3 |
5 |
2 |
4 |
|
|
|
RR q=1 |
完成时间 |
12 |
10 |
18 |
11 |
17 |
|
|
周转时间 |
12 |
9 |
16 |
8 |
13 |
11.6 |
|
|
带权周转时间 |
3 |
3 |
3.2 |
4 |
3.25 |
3.29 |
|
|
RR q=4 |
完成时间 |
4 |
7 |
18 |
13 |
17 |
|
|
周转时间 |
4 |
6 |
16 |
10 |
13 |
9.8 |
|
|
带权周转时间 |
1 |
2 |
3.2 |
5 |
3.25 |
2.89 |
5、 概要设计
抽象数据类型定义:
// 时间片
publicstatic int q = 0;
//允许的最大进程数
publicstatic int MaxNum = 100;
//真实的进程数
publicstatic int realNum;
//order数组的1个下标
publicstatic int number;
//当前时间
publicstatic int NowTime;
//各进程的到达时间
publicstatic int ArrivalTime[] = new int[MaxNum];
//各进程的服务时间
publicstatic int ServiceTime[] = new int[MaxNum];
//各进程的服务时间(用于记录进程服务时间随时间片轮转减少的进程)
public static int PServiceTime[] = new int[MaxNum];
//各进程的完成时间
publicstatic int FinishTime[] = new int[MaxNum];
//各进程的周转时间
publicstatic int WholeTime[] = new int[MaxNum];
// 进程调度队列(寄存的是各个进程的数字代号,如进程A数字代号为1)
public static int order[] = new int[MaxNum];
// 各进程的带权周转时间
publicstatic double WeightWholeTime[] = new double[MaxNum];
//平均周转时间、平均带权周转时间
public static double AverageWT, AverageWWT;
//周转时间总和
publicstatic int SumWT = 0;
//带权周转时间总和
publicstatic double SumWWT = 0;
//进程是不是已结束的标志
publicstatic boolean Finished[] = new boolean[MaxNum];
public static Scanner input;主程序的流程:

各模块之间的层次关系:只有Main方法
6、 详细设计
代码详见附录
7、 调试分析
(1)调试进程中遇到的问题及解决办法
本次实验比较简单。
(2)算法的性能分析
基本操作:all_add++;
时间复杂度:O(服务时间/ q * (n⑴))
(3)经验和体会
本次实验比较简单。
8、 测试结果
时间片q为1时的输出

时间片q为4输出

7、附录(java)
importjava.io.BufferedInputStream;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.util.Scanner;
publicclass RR {
// 时间片
public static int q = 0;
// 允许的最大进程数
public static int MaxNum = 100;
// 真实的进程数
public static int realNum;
// order数组的1个下标
public static int number;
// 当前时间
public static int NowTime;
// 各进程的到达时间
public static int ArrivalTime[] = newint[MaxNum];
// 各进程的服务时间
public static int ServiceTime[] = newint[MaxNum];
// 各进程的服务时间(用于记录进程服务时间随时间片轮转减少的进程)
public static int PServiceTime[] = newint[MaxNum];
// 各进程的完成时间
public static int FinishTime[] = newint[MaxNum];
// 各进程的周转时间
public static int WholeTime[] = newint[MaxNum];
// 进程调度队列(寄存的是各个进程的数字代号,如进程A数字代号为1)
public static int order[] = new int[MaxNum];
// 各进程的带权周转时间
public static double WeightWholeTime[] = newdouble[MaxNum];
// 平均周转时间、平均带权周转时间
public static double AverageWT, AverageWWT;
// 周转时间总和
public static int SumWT = 0;
// 带权周转时间总和
public static double SumWWT = 0;
// 进程是不是已结束的标志
public static boolean Finished[] = newboolean[MaxNum];
public static Scanner input;
public static void main(String[] args)throws FileNotFoundException {
System.out.println("请输入时间片q:");
input = new Scanner(System.in);
q = input.nextInt();
// 从文件中输入数据
BufferedInputStream in = newBufferedInputStream(new FileInputStream("test.txt"));
System.setIn(in);
input = new Scanner(System.in);
realNum = input.nextInt(); // 真实进程数
for (int i = 0; i < realNum; i++) {// 各进程的到达时间
ArrivalTime[i] = input.nextInt();
}
for (int j = 0; j < realNum; j++) {// 各进程的服务时间
ServiceTime[j] = input.nextInt();
PServiceTime[j] =ServiceTime[j]; //用于记录进程服务时间随时间片轮转减少的进程
Finished[j] = false;
}
//关闭文件流
input.close();
int all_add = 1; //就绪队列中的进程个数
order[0] = 0; //进程调度队列(寄存的是各个进程的数字代号,如进程A数字代号为1)
number = 1;
NowTime = 0; //当前时间
while (order[0] != 100) { //order[0]为100,是认为规定进程调度结束的标志
// 调度进程A
char w = 'A';
System.out.println("时刻"+ NowTime + ":进程" + (char)(w + order[0]) + "开始运行;");
if (PServiceTime[order[0]] > q){ //进程还未完成
PServiceTime[order[0]] = PServiceTime[order[0]]- q; //对应进程的服务时间减去1个时间片
NowTime += q; //当前时间增加1个时间片
System.out.println("时刻"+ NowTime + ":进程" + (char)(w + order[0]) + "停止运行,加入就绪序列尾;");
} else { //进程剩1个时间片后结束
NowTime +=PServiceTime[order[0]]; //当前时间增加1个时间片
PServiceTime[order[0]] = 0; //对应进程的服务时间归零
System.out.println("时刻"+ NowTime + ":进程" + (char)(w + order[0]) + "运行结束;");
FinishTime[order[0]] = NowTime;
WholeTime[order[0]] = NowTime -ArrivalTime[order[0]];//周转时间 = 完成时间 - 到达时间
WeightWholeTime[order[0]] = 1.0* WholeTime[order[0]] / ServiceTime[order[0]];//带权周转时间 = 周转时间 / 服务时间
}
// 将到达的进程加入序列尾
if (all_add < realNum) {
for (int i = 1; i < realNum;i++) {
if (NowTime >=ArrivalTime[i] && Finished[i] == false) { //判断该进程是不是已在就绪队列中
order[number++] = i;
all_add++;
Finished[i] = true;
}
}
}
// 将序列首程序调到序列尾
int temp = order[0];
for (int i = 0; i < number - 1;i++){ //将order中的每一个数前移1位
order[i] = order[i + 1];
}
if (PServiceTime[temp] == 0){ //进程已将全部调度结束,通过将order的第1个数标记为100,来结束进程调度
order[--number] = MaxNum;
}else{ //进程还未调度结束
order[number - 1] = temp;//加入就绪队列队尾
}
}
double all = 0, all1 = 0;
for (int i = 0; i < realNum; i++) {//计算总周转时间和总带权周转时间
all += WholeTime[i];
all1 += WeightWholeTime[i];
}
System.out.println("\n进程名\t到达时间\t服务时间\t完成时间\t周转时间\t带权周转时间");
for (int i = 0; i <realNum; i++) {
System.out.println((char)(i + 'A') +"\t" + ArrivalTime[i] + "\t"
+ ServiceTime[i] +"\t" + FinishTime[i] + "\t"
+ WholeTime[i] +"\t" + WeightWholeTime[i]);
}
AverageWT = all / realNum; //平均周转时间 = 周转总时间 / 作业个数
System.out.println("平均周转时间:"+ AverageWT);
AverageWWT = all1 / realNum; //评均带权周转时间 = 带权周转总时间 / 作业个数
System.out.println("平均带权周转时间:" + AverageWWT);
}
}