1. 实验目的
用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。
2. 实验内容与要求
① 编写并调试一个单道处理系统的作业调度模拟程序。(必做)
作业调度算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRRN)的调度算法。
对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间,以比较各种算法的优缺点。
② 编写并调度一个多道程序系统的作业调度模拟程序。(选做)
作业调度算法:采用基于先来先服务的调度算法或基于优先级的作业调度算法。其余可以参考课本中的方法进行设计。
对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。
3. 流程图与模块调用
4. 实验分析
① 初始化作业
def __init__(self, id, cputime) :
# id:序号 cputime: #作业预计所需时间
self.id = id
self.prior = 0 #HRRN中所需优先级
self.cputime = cputime
self.state = 0 # 0表示Wait 1表示Run 2表示Finish
self.starttime = 0 #进程开始时间
self.endtime = 0 #进程结束时间
② 先来先服务算法
def FCFS(workL): #先来先服务算法
count = 0 #时间片
for i in workL:
i.state = 1
i.starttime = count
count += i.cputime
i.endtime = count
i.state = 2
i.Do_FCFS()
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
③ 最短作业优先
def SJF(workL): #短作业优先调度算法
count = 0
sort_SJF(workL)
for i in workL:
i.state = 1
i.starttime = count
count += i.cputime
i.endtime = count
i.state = 2
i.Do_SJF()
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
④ 高响应比优先
def HRRN(workL): #响应比高者优先调度算法
count = 0
while workL[0].state == 0: #首部是0就说明还有作业没执行完
workL[0].state = 1
workL[0].starttime = count
count += workL[0].cputime
workL[0].endtime = count
workL[0].state = 2
workL[0].Do_HRRN()
workL.append(workL[0]) #将完成的作业移到序列尾部
del workL[0]
sort_HRRN(workL, count)
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime # 完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime / i.cputime
print(('平均周转时间:%.2f' + ' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
5. 总代码
import random
#coding:utf-8
##这是单道处理系统作业的调度模拟,包括FCFS(先来先服务)、SJF(短作业优先)、HRRN(响应比高着优先)算法。
class JCB :
def __init__(self, id, cputime) :
# id:序号 cputime:作业预计所需时间
self.id = id
self.prior = 0 #可作为HRRN中需要的优先级,一开始为0,随着调度、等待而改变;
self.cputime = cputime
self.state = 0 # 0表示Wait 1表示Run 2表示Finish
self.starttime = 0 #进程开始运行的时间
self.endtime = 0 #进程结束运行时间
def work_init(self):
print(("作业序列%-2d" + "时间%-2d")%(self.id,self.cputime))
def Do_HRRN(self) : #输出HRRN法作业调度情况
Turnaround = self.endtime #周转时间= 完成时间-提交时间
Daiquan = Turnaround / self.cputime #带权周转时间:周转时间/运行所需时间
print(("作业:%-2d" +" 优先权:%-2d"+ " 所需CPU时间:%-2d" +" 开始运行时间:%-2d"
+ " 结束运行时间:%-2d" +" 周转时间:%.2f" + " 带权周转时间:%.2f")%
(self.id,self.prior,self.cputime,self.starttime,self.endtime,Turnaround, Daiquan))
def Do_FCFS(self) : #输出FCFS法作业调度运行情况
Turnaround = self.endtime
Daiquan = Turnaround / self.cputime
print(("作业:%-2d" + " 所需CPU时间:%-2d" + " 开始运行时间:%-2d"
+ " 结束运行时间:%-2d"+" 周转时间:%.2f" + " 带权周转时间:%.2f") %
(self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))
def Do_SJF(self) : #输出SJF法作业调度运行情况
Turnaround = self.endtime
Daiquan = Turnaround / self.cputime
print(( "作业:%-2d" + " 所需CPU时间:%-2d" + " 开始运行时间:%-2d"
+ " 结束运行时间:%-2d"+" 周转时间:%.2f" + " 带权周转时间:%.2f") %
(self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))
def init(num) : #创建数目确定的jcb块,按顺序放入列表中
jcbList = []
for i in range(num) :
jcbList.append(JCB(i, random.randint(1, 20)))
# 将随机产生的n个作业保存,创建id和预计CPU时间
for i in jcbList: #输出最开始时进程情况
i.work_init()
return jcbList
def sort_SJF(workL): #将初始化的序列,按照作业的时间,从小到大排列。
for i in range(0, len(workL) - 1):
for j in range(i+1, len(workL)):
if workL[i].cputime > workL[j].cputime :
workL[i], workL[j] = workL[j], workL[i]
return workL
def sort_HRRN(workL, count): #每次执行完上一个作业,对剩余作业排序,响应比作为优先级,优先级高的排前面
#优先级=(等待时间+cputime)/cputime 这里的等待时间可以理解为就是时间量T,因为参与排序的肯定是还没执行的作业
#先计算待处理的作业的优先级,将finish的排到最后,并且将优先级最高的排到第一位
for i in workL:
i.prior = (count + i.cputime)/i.cputime
for i in range(len(workL) - 1, 0, -1): #finish的转移到尾部,然后只遍历状态为0的
if workL[i].state == 2:
continue
if workL[i].prior > workL[i - 1].prior :
workL[i], workL[i - 1] = workL[i - 1], workL[i]
def FCFS(workL): #先来先服务调度算法
count = 0 #时间片0 即指导书中的时间量T0=0
for i in workL:
i.state = 1
i.starttime = count #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
count += i.cputime
i.endtime = count
i.state = 2
i.Do_FCFS()
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
def SJF(workL): #短作业优先调度算法
count = 0
sort_SJF(workL)
for i in workL:
i.state = 1
i.starttime = count #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
count += i.cputime
i.endtime = count
i.state = 2
i.Do_SJF()
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
def HRRN(workL): #响应比高者优先调度算法
count = 0
while workL[0].state == 0: #只要首部还是0就说明还有作业没执行完
workL[0].state = 1
workL[0].starttime = count
count += workL[0].cputime
workL[0].endtime = count
workL[0].state = 2
workL[0].Do_HRRN()
workL.append(workL[0]) #将完成的作业移到序列尾部
del workL[0]
sort_HRRN(workL, count)
Turnaround_time = 0
daiquan_time = 0
for i in workL : # 计算平均周转时间
Turnaround_time += i.endtime # 完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime / i.cputime
print(('平均周转时间:%.2f' + ' 平均带权周转时间%.2f') % (Turnaround_time / len(workL), daiquan_time / len(workL)))
def main():
Num = int(input("作业数量:"))
print("请选择你的进程调度方法")
print("A.FCFS B.SJF C.HRRN ")
method = input("你的选择是:")
WorkL = init(Num)
if method == 'A':
FCFS(WorkL)
elif method == 'B':
SJF(WorkL)
elif method == 'C':
HRRN(WorkL)
if __name__ == '__main__':
main()
6. 运行情况
① 先来先服务算法
② 最短作业优先算法
③ 高响应比优先算法