操作系统实验一
进程调度算法
一、实验目的
1.理解操作系统进程管理中进行进程调度的过程和调度算法的思想原理;
创建进程控制块PCB,并合理组织就绪队列。
2.理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。
掌握几种调度算法。
-
理解几种进程调度的方式
-
用代码将几种进程调度的方式表现出来
二、实验原理
(1)先到先服务调度算法:按照进程提交给系统的先后次序来进行调度。
(2)短作业优先调度算法:按照进程所要求的运行时间来衡量。
(3)时间片轮转调度算法:根据先来先服务排序,以一个时间片为单位,依次执行不同的进程。
(4)优先权调度算法:按照进程的优先权来衡量。
三、实验要求
能够考虑社会、健康、安全、法律、文化及环境等因素的影响,针对先来先服务、短进程优先、时间片轮转、高相应比优先调度算法进行建模,设计实验方案,运用恰当的集成开发工具编程模拟实现上述算法,要求:
- 有录入界面,动态录入进程个数、时间片大小、创建进程控制块(PCB)通过录入界面录入进程标识符、进程到达时间、服务时间等信息;
- 有算法选择界面,能够根据需要选择不同调度算法;
- 有输出界面,能够输出不同调度算法下诸进程的进程标识符、到达时间、服务时间、开始时间、完成时间、周转时间、带权周转时间以及一批作业的平均周转时间、平均带权周转时间;
四、实现过程
- 定义一个静态内部类,代码初始化时优先加载,放入进程标识符、进入时间以及服务时间等
- 将进程放入到一个数组中
- 对于FCFS算法思想:因为是按照进入时间的前后作为进入内存的优先级,所以先按照进入时间从小到大排序,使用直接选择排序算法,将进程按照进入时间排成从小到大的队列,设置一个标志位,temover记录上次进程的结束时间,需要考虑:如果上一个结束的时间比这个进程进入时间大,则这个进程已经进入,需要等待到temover时间才能开始,直接使用temover作为这个进程的开始时间。
- 对于SJF算法思想:先按照进入时间从小到大排序,然后对进来的进程再次进行排序,这次排序需要按照服务时间进行排序。
- 对于高响应比优先级算法:首先要知道优先级的计算公式,然后还是先按照进入时间排序,再按照优先级排序
- 对于RR算法:照样是先按照进入时间进行排序,然后创建一个队列queue,将进程放入队列中。
五、实现截图
六、源代码
注解挺多,可以作为参考
package com.zkb;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class process {
static class pro{
public String name; //进程标识符
public int insertTime;//进入时间
public int serviceTime;//服务时间
public int startTime;//开始时间
public int overTime;//完成时间
public int turnoverTime;//周转时间
public double turnAroundTime;//带全周转时间
}
pro[] processes;
public void init(){
Scanner scanner = new Scanner(System.in);
System.out.println("你要输入的进程数:");
int amount = scanner.nextInt();
processes = new pro[amount];
for (int i=0;i<amount;i++){
System.out.println("第"+(i+1)+"进程是:");
System.out.println("请输入你的进程名");
processes[i] = new pro();
processes[i].name= scanner.next();
System.out.println("你的进入时间是:");
processes[i].insertTime = scanner.nextInt();
System.out.println("你的估计运行时间是:");
processes[i].serviceTime = scanner.nextInt();
}
}
//先来先服务进程调度算法
public void FCFS(){
sort();
int temover=0;//记住每次进程结束的时间,作为下次的开始时间
for (int i = 0; i < processes.length; i++) {
if (i==0){
processes[i].startTime = processes[i].insertTime;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;//记住结束的时间
}else {//如果上一个结束的时间比这个进程进入时间大,则这个进程已经进入
//需要等待到temover时间才能开始,直接使用temover作为这个进程的开始时间
if (temover>=processes[i].insertTime){
processes[i].startTime=temover;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;
}else{
//否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
processes[i].startTime = processes[i].insertTime;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;//记住结束的时间
}
}
computationTime();//计算周转时间和带全周转时间
}
}
//短进程优先算法
public void SJF(){
sort();
int temover= processes[0].insertTime;
for (int i = 0; i < processes.length; i++) {
int effect = effective(temover,i);//查看进来了几个进程
sort1(i,effect);//对进来的进程进行排序
if(temover >= processes[i].insertTime){
processes[i].startTime=temover;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;
}else {
//否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
processes[i].startTime = processes[i].insertTime;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;//记住结束的时间
}
}
computationTime();
}
//优先级调度算法
public void priority(){
sort();
int temover= processes[0].insertTime;
for (int i = 0; i < processes.length; i++) {
int effect = effective(temover,i);//查看进来了几个进程
sort2(i,effect,temover);//对进来的进程进行优先级排序
if(temover >= processes[i].insertTime){
processes[i].startTime=temover;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;
}else {
//否则这个进程还没有进入,需要等到这个进程的进入时间才能开始
processes[i].startTime = processes[i].insertTime;
processes[i].overTime = processes[i].startTime+processes[i].serviceTime;
temover = processes[i].overTime;//记住结束的时间
}
}
computationTime();
}
//时间片调度算法
public void RR(){
sort();//首先按照进入的时间进行排个小序
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的时间片是多少:");
int RR = scanner.nextInt();
int temover = processes[0].insertTime;//记录上个进程结束时间
Queue<Integer> queue = new LinkedList<>();//建一个队列去更新进来的进程,模拟进程调度
int[] serviceTem = new int[processes.length];//存放所有的进程估计运行的时间的,开始全部置位0
int i=1; //看队列进入了几个进程
queue.offer(0);//排完序,肯定先执行第一个
while (!queue.isEmpty()||i<processes.length){
//RR的值重新赋予
int cur=RR;
//如果某一个当某一个进程执行完之后,但后面的进程还没有入队,就会有队列为空的表现.
// 所以他就得再次执行陷入先服务,所以我们得给队列手动进入后面的进程.
if (queue.isEmpty()){
for (int tep = 0; tep < processes.length; tep++) {
if (serviceTem[tep]==0){
queue.offer(tep);
temover = processes[tep].insertTime;//更改下结束时间
i=i+1;
break;
}
}
}
//出队列,进行执行
int tem=queue.poll();
if (serviceTem[tem]==0){//当数组里估计运行时间为0的话,那就是第一次初始化,可以进行赋初值
processes[tem].startTime=temover;
}
while(cur!=0){//模拟实现时间片轮转,执行RR次,只等相等或者用完时间片
if (serviceTem[tem]!=processes[tem].serviceTime){
++serviceTem[tem];
temover++;
}
if (serviceTem[tem] == processes[tem].serviceTime){
processes[tem].overTime = temover;
break;
}
cur--;
}
//注意我这个进程进入顺序.
//i记录进程个数,去遍历所有进程,看还有那个没进入,如果进程到了,就插入队列.
if (i<processes.length){
int j=i;
for (; j < processes.length ;j++) {
if (processes[j].insertTime<=temover){
queue.offer(j);
i=i+1;
}
}
}
//如果当前进程没有执行完,就再次进入队列
if (serviceTem[tem] != processes[tem].serviceTime){
queue.offer(tem);
}
}
computationTime();
}
public void print(){
System.out.println("| 作业 | 进入时间 | 估计运行时间 | 开始时间 | 结束时间 | 周转时间 | 带权周转时间 |");
System.out.println("----------------------------------------------------------------------------------------------");
for(int i = 0; i < processes.length; i++){
System.out.print("| " + processes[i].name + " |");
System.out.print(" " + processes[i].insertTime + " |");
System.out.print(" " + processes[i].serviceTime + " |");
System.out.print(" " + processes[i].startTime + " |");
System.out.print(" " + processes[i].overTime + " |");
System.out.print(" " + processes[i].turnoverTime + " |");
System.out.printf("%11.2f", processes[i].turnAroundTime);
System.out.print(" |");
System.out.println();
// System.out.printf(" " + processes[i].turnAroundTime + " |");
}
double s=0,t=0,a=0,b=0;
for(int i = 0; i < processes.length; i++) {
s=s+processes[i].turnoverTime;
a = a + processes[i].turnAroundTime;
}
t=s/processes.length;
b=a/processes.length;
System.out.println("平均周转时间:" +t);
System.out.println("平均带权周转时间:"+b);
System.out.println("----------------------------------------------------------------------------------------------");
}
public void menu() {
System.out.println("欢迎来到进程调度");
System.out.println("***********************");
System.out.println("*****1.初始化**********");
System.out.println("*****2.FCFS算法********");
System.out.println("*****3.SJF算法*********");
System.out.println("*****4.优先级算法******");
System.out.println("*****5.RR算法**********");
System.out.println("*****6.exit************");
System.out.println("***********************");
}
public void perform(){
Scanner scanner = new Scanner(System.in);
int choice = 0;
while(true) {
menu();
System.out.println("请输入你的选择");
choice = scanner.nextInt();
if (choice == 1) {
init();
} else if (choice == 2) {
System.out.println("FCFS算法结果:");
FCFS();
} else if (choice == 3) {
System.out.println("SJF算法结果:");
SJF();
} else if (choice == 4){
System.out.println("优先级算法结果:");
priority();
}
else if(choice == 5){
System.out.println("RR算法结果:");
RR();
}
else if (choice == 6) {
System.out.println("Good bye !!!");
break;
}
else{
System.out.println("你的输入有误,请重输");
continue;
}
print();
}
}
public static void main(String[] args) {
process m1 = new process();
m1.perform();
}
private void sort2(int start, int end, int temover) {//根据优先级排序
for (int i = start; i < end ; i++) {
for (int j = i+1; j < end ; j++) {
int now = (temover-processes[i].insertTime+processes[i].serviceTime)/processes[i].serviceTime;
int next = (temover-processes[j].insertTime+processes[j].serviceTime)/processes[j].serviceTime;
if (next>now){
pro tem= processes[i];
processes[i] = processes[j];
processes[j] = tem;
}
}
}
}
private void sort1(int start, int end) {//根据服务时间排序
for (int i = start; i < end ; i++) {
for (int j = i+1; j < end ; j++) {
if (processes[i].serviceTime>processes[j].serviceTime){
pro tem= processes[i];
processes[i] = processes[j];
processes[j] = tem;
}
}
}
}
private int effective(int temover, int start) {
int end;//返回有效值的下标
for(end = start;end<processes.length;end++){
if (processes[end].insertTime>temover){
break;
}
}
return end;
}
private void computationTime() {
for (int i = 0; i < processes.length; i++) {
processes[i].turnoverTime=processes[i].overTime-processes[i].insertTime;
processes[i].turnAroundTime = (double) processes[i].turnoverTime/processes[i].serviceTime;
}
}
private void sort() {//根据进入时间直接选择排序
for (int i = 0; i < processes.length; i++) {
for (int j = i+1; j <processes.length ; j++) {
if (processes[i].insertTime>=processes[j].insertTime){
pro tem= processes[i];
processes[i] = processes[j];
processes[j] = tem;
}
}
}
}
}
= 0; i < processes.length; i++) {
for (int j = i+1; j <processes.length ; j++) {
if (processes[i].insertTime>=processes[j].insertTime){
pro tem= processes[i];
processes[i] = processes[j];
processes[j] = tem;
}
}
}
}
}