操作系统实验一:处理器管理
实验报告
一、实验目的
(1)加深对处理机调度的作用和工作原理的理解。
(2)进一步认识并发执行的实质。
二、实验要求:
本实验要求用高级语言,模拟在单处理器情况下,采用多个调度算法,对N个进程进行进程调度。语言自选。
并完成实验报告。
三、实验内容:
在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。
当就绪状态进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。
- 进程及进程队列的表示。
- 处理器调度算法:FCFS,SJF,RR,HRRN,MLFQ等
- 跟踪进程状态的转化
- 输出:系统中进程的调度次序,计算CPU利用率,平均周转时间和平均带权周转时间
四、实验过程与结果
- 算法思想与设计
- 算法实现代码
- 运行结果
示例:
进程定义:
进程队列:
调度算法:
1.RR算法:
1.1 算法思想:
- CPU时间划分为时间片,例如100ms
- 时间片调度:调度程序每次把CPU分配给就绪队列首进程使用一个时间片,就绪队列中的每个进程轮流地运行一个时间片。当这个时间片结束时,强迫一个进程让出处理器,让它排列到就绪队列的尾部,等候下一轮调度
1.2 算法设计:(采用描述或程序流程图)
Ø进程排序
Ø队列不为空时循环:
Ø到达?
Ø剩余服务时间>时间片
Ø运行时间
Ø剩余服务时间
Ø剩余服务时间<=时间片
Ø运行时间
Ø剩余服务时间、完成时间、周转时间、加权周转时间
Ø保存
Ø从队列删除进程
1.3 算法实现代码
class Process: def init(self,name,arrive_time,serve_time): self.name=name self.arrive_time=arrive_time self.serve_time=serve_time self.left_serve_time=serve_time self.fish_time=0 self.cycling_time=0 self.w_cycling_time=0 process_list=[] processA=Process('A',0,4) processB=Process('B',1,3) processC=Process('C',2,4) processD=Process('D',3,2) processE=Process('E',4,4) process_list.append(processA) process_list.append(processB) process_list.append(processC) process_list.append(processD) process_list.append(processE) for p in process_list: print(p.name,p.arrive_time,p.serve_time) process_list.sort(key=lambda x:x.arrive_time) for p in process_list: print(p.name,p.arrive_time,p.serve_time,p.left_serve_time, p.finish_time,p.cycling_time,p.w_cycling_time) len(process_list) q = 2 index = int(0) running_time=int(0) pf = [] while len(process_list)>0: p = process_list[index] if p.arrive_time>running_time: running_time=p.arrive_time if p.left_serve_time>q: print(p.name,q) running_time+=q p.left_serve_time-=q else: print(p.name,p.left_serve_time) running_time+=p.left_serve_time p.left_serve_time-=0 p.finish_time=running_time p.cycling_time=p.finish_time-p.arrive_time p.w_cycling_time=p.cycling_time/p.serve_time print('--',p.name,p.arrive_time,p.serve_time,p.left_serve_time, p.finish_time,p.cycling_time,p.w_cycling_time) pf.append(p) process_list.remove(p) index -= 1 index += 1 if index >= len(process_list): index=0
1.4 运行结果
2. FCFS算法:
2.1 算法思想:
按照作业进入系统后备作业队列的先后次序来挑选作业,先进入系统的作业将优先被挑选进入内存,创建用户进程,分配所需资源,然后移入就绪队列。
2.2 算法设计:(采用描述或程序流程图)
Ø进程排序
Ø按照作业到达顺序创建进程队列
Ø前一个作业结束移出进程队列
Ø后一个作业开始执行
Ø所有作业执行完毕
Ø运行时间 = 服务时间
Ø完成时间 += 运行时间
Ø周转时间 = 完成时间
Ø带权周转时间 = 周转时间 / 服务时间
Ø保存
Ø从队列删除进程
2.3 算法实现代码
Process.java package fcfs; public class Process { float serveTime,finishTime; float cyclingTime; float wcyclingTime; //定义设置作业服务时间的方法 public void setServeTime(float serveTime) { this.serveTime = serveTime; } //定义进程执行方法 public void runProcess(Process arr[]){ float runningTime=0,sumcyclingTime=0,sumwcyclingTime=0; System.out.println("进程各作业的所需的服务时间为:"); for (int i = 0; i < arr.length; i++) { System.out.println("作业"+(i+1)+":"+(int)arr[i].serveTime+" ms"); } System.out.println("----------------------------------"); for (int i = 0; i < arr.length; i++) { runningTime += arr[i].serveTime; arr[i].finishTime = runningTime; arr[i].cyclingTime = arr[i].finishTime; arr[i].wcyclingTime = arr[i].cyclingTime/arr[i].serveTime; sumcyclingTime += arr[i].cyclingTime; sumwcyclingTime += arr[i].wcyclingTime; System.out.println("作业"+(i+1)+"的作业周转时间为:"+(int)arr[i].cyclingTime+" ms"); System.out.println("带权周转时间为:"+arr[i].wcyclingTime+" ms"); System.out.println("----------------------------------"); } System.out.println("平均周转时间为:"+sumcyclingTime/arr.length+" ms"); System.out.println("平均周转时间为:"+sumwcyclingTime/arr.length+" ms"); } } Main.java package fcfs; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub //设置各个作业所需CPU的时间,并将作业存放在数组arr中 Process A = new Process(); A.setServeTime(28); Process B = new Process(); B.setServeTime(9); Process C = new Process(); C.setServeTime(3); Process arr[] = {A,B,C}; Process process = new Process(); //调用实现FCFS先来先服务算法的方法 process.runProcess(arr); } }
2.4 运行结果
3.SJF算法:
3.1算法思想:
最短作业优先算法以进入系统作业所要求的CPU运行时间的长短为标准,总是选取预计就算时间最短的作业投入运行。
2.2 算法设计:(采用描述或程序流程图)
Ø进程排序
Ø按照作业时间长短排序,以短作业优先原则创建进程对列
Ø前一个作业结束移出进程队列
Ø后一个作业开始执行
Ø所有作业执行完毕
Ø运行时间 = 服务时间
Ø完成时间 += 运行时间
Ø周转时间 = 完成时间
Ø带权周转时间 = 周转时间 / 服务时间
Ø保存
Ø从队列删除进程
2.3 算法实现代码
Process.java package sjf; public class Process { public void runProcess(int processlist[]){ System.out.println("进程中的作业列表为:"); System.out.println("-------------------------"); System.out.println("作业名 "+"所需CPU时间"); for (int i = 0; i < processlist.length; i++) { System.out.println(" 作业"+(i+1)+" "+processlist[i]); } //创建一个新数组,并将数组元素设置成与processlist中的元素一致 int[] arr = new int[processlist.length]; for(int i=0;i<processlist.length;i++){ arr[i] = processlist[i]; } //调用排序方法将数组arr中的元素按从小到大排序 int arr1[] = Sort(arr); int runningTime = 0; int cyclingTime = 0,sumcyclingTime = 0; float wcyclingTime = 0,sumwcyclingTime = 0; System.out.println("-------------------------"); System.out.println("执行顺序为:"); //按照作业时间长短排序,并输出执行作业的顺序 for (int i = 0; i < arr1.length; i++) { for(int j = 0;j < processlist.length;j++) { if(arr1[i]==processlist[j]){ System.out.println("作业"+(j+1)); } } } System.out.println("-------------------------"); System.out.println("按作业顺序"); System.out.println("各个作业的周转和带权周转时间依次为:"); //按作业顺序计算各个作业的周转和带权周转时间 for (int i = 0; i < arr1.length; i++) { runningTime += arr1[i]; cyclingTime = runningTime; sumcyclingTime +=cyclingTime; System.out.println("-------------------------"); System.out.println("周转时间:"+cyclingTime); wcyclingTime = (float)cyclingTime/arr1[i]; System.out.println("带权周转时间:"+wcyclingTime); sumwcyclingTime += wcyclingTime; } //计算进程运行总时间、平均周转时间和平均带权周转时间 System.out.println("-------------------------"); System.out.println("进程运行总时间为:"+runningTime); System.out.println("平均周转时间为:"+sumcyclingTime/arr1.length); System.out.println("平均带权周转时间为:"+sumwcyclingTime/arr1.length); } //定义按作业时间排序的方法 public int[] Sort(int []arr){ int temp=0; for (int i = 0; i < arr.length-1; i++) { for(int j = i+1;j<arr.length;j++) { if(arr[i]>arr[j]) { temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } return arr; } } Main.java package sjf; public class Main { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Process process = new Process(); //设置进程作业所需CPU的时间,并存放在数组processlist中 int []processlist = {9,4,10,8}; //调用实现SJF短作业优先算法的方法 process.runProcess(processlist);; } }
3.4 运行结果
4. HRRN算法:
4.1算法思想:
- 只有一个作业时按FCFS原则执行,同时存在多个作业是,计算每个作业的响应比
- 响应比 = 1 + 作业等待时间 / 作业处理时间
- 响应比最高的先执行,执行结束后,在所剩的作业中再求响应比,响应比高者执行,以此类推直至所有作业执行完毕
4.2算法设计:
Ø进程排序
Ø队列不为空时循环:
Ø到达?
Ø是否多个作业同时到达
Ø若只有一个作业到达,则先完成此作业
Ø若多个作业同时到达,则计算每个作业的响应比,按照响应比最高者优先执行的原则执行作业
Ø循环直至作业全部作业执行完毕
Ø剩余服务时间 <= 时间片
Ø运行时间 = 剩余服务时间 = 完成时间
Ø周转时间 = 完成时间 – 到达时间
Ø加权周转时间 = 周转时间 / 运行时间
Ø保存
Ø从队列删除进程
5.MLFQ算法:
5.1 算法思想:
- 现设定采用三级反馈队列调度算法
- CPU时间划分为三个时间片,分别为2、4、8 ms
- 处理器调度:每次先从第一个队列中选取执行者,同一队列中的进程/线程按FCFS原则排队,只有在未选到时才从较低一级的就绪队列中选取,仅当前面所有队列为空时才会运行最后一个就绪队列中的进程/线程。
5.2 算法设计:(采用描述或程序流程图)
Ø进程排序
Ø队列不为空时循环:
Ø到达?
Ø剩余服务时间>时间片
Ø运行时间 += 时间片
Ø剩余服务时间 -= 时间片
Ø降低优先级,置于第二队列,分配较长的时间片
Ø下一作业是否到达?
Ø下一作业到达,进入第一队列并执行
Ø下一作业未到达,在第二队列中继续执行本作业
Ø循环直至作业全部作业执行完毕
Ø剩余服务时间 <= 时间片
Ø运行时间 = 剩余服务时间 = 完成时间
Ø周转时间 = 完成时间 – 到达时间
Ø加权周转时间 = 周转时间 / 运行时间
Ø保存
Ø从队列删除进程