(1) 编写并调试一个单道处理系统的作业调度模拟程序。
作业调度算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRRN)的调度算法。
对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间,以比较各种算法的优缺点。
(2) 编写并调度一个多道程序系统的作业调度模拟程序。
作业调度算法:采用基于先来先服务的调度算法或基于优先级的作业调度算法。其余可以参考课本中的方法进行设计。
对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。
在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
作业调度算法:采用先来先服务(FCFS)调度算法,即按作业提交的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。各个等待的作业按照提交时刻的先后次序排队,总是首先调度等待队列中队首的作业。每个作业完成后要打印该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后要计算并打印这组作业的平均周转时间、带权平均周转时间。
(1)在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素
(2)高响应比怎么体现?
在进程调度中,pcb类中添加了2个和优先级有关的类属性,静态优先级prior和动态优先级dy_prior。那在JCB类中,并不需要显示初始的优先级,因为初始的优先级一定为0,所以可以将动态优先级这个属性删除,随着作业调度,执行作业的操作的时间变化,每次执行完上一个作业就计算当前的各个作业的优先级,并赋值prior。
(3)SJF算法也很简单,虽然多了一个优先级的概念,但是一个确定作业序列中,每个作业的所需时长已知,那我干脆将这个作业序列,按照每个序列的时长,从小到大排列,然后再进行FCFS的调度就好了。
(4)HRRN响应比高者优先调度算法也是按照优先级先后调度,这里的优先级和SJF不同,这肯定是动态变化的,有点类似动态优先级调度,但是更简单。这里的优先级=(等待时间+要求服务时间)/要求服务时间。等待的时间和所需要的时间的和刚好是系统对该作业的响应时间。而这个比值看分母,说明该算法还是偏袒时间短的作业,等待时间相同时,作业越短,获得执行的几率越高。
因为每次都要计算优先级,所以就没法直接对序列循环了。更类似实验一的算法了。
我是这么解决的,每次都执行序列首部的作业。在执行了上一个作业后,将执行完的作业移动位置到序列尾部,然后对剩下的len(list)-len(state=finish)个挑选当前优先级最大的到序列首部。都是O(n)个复杂度。
而id=0的就是默认的t0=0时,等待时间最长的,所以虽然一开始首部的优先级是0,但是他应该是第一个执行的
import random
##这是单道处理系统作业的调度模拟,包括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 out_init(self):
print(("初始化JCB序列:%-2d" + "预计所需时间:%-2d")%(self.id,self.cputime))
def outSituation_HRRN(self) : #输出HRRN法作业调度情况
Turnaround = self.endtime #周转时间= 完成时间-提交时间
Daiquan = Turnaround / self.cputime #带权周转时间:周转时间/运行所需时间
print(("HRRN法: "+"作业:%-2d" +" 优先权:%-2d"+ " 作业所需CPU时间:%-2d" +" 开始运行时间:%-2d"
+ " 结束运行时间:%-2d" +" 周转时间:%.2f" + " 带权周转时间:%.2f")%
(self.id,self.prior,self.cputime,self.starttime,self.endtime,Turnaround, Daiquan))
def outSituation_FCFS(self) : #输出FCFS法作业调度运行情况
Turnaround = self.endtime
Daiquan = Turnaround / self.cputime
print(("FCFS: " + "作业:%-2d" + " 作业所需CPU时间:%-2d" + " 开始运行时间:%-2d"
+ " 结束运行时间:%-2d"+" 周转时间:%.2f" + " 带权周转时间:%.2f") %
(self.id, self.cputime, self.starttime, self.endtime,Turnaround, Daiquan))
def outSituation_SJF(self) : #输出SJF法作业调度运行情况
Turnaround = self.endtime
Daiquan = Turnaround / self.cputime
print(( "SJF法: "+"作业:%-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时间
print("刚生成的各进程")
for i in jcbList: #输出最开始时进程情况
i.out_init()
return jcbList
def sort_SJF(jcbList): #将初始化的序列,按照作业的时间,从小到大排列。
for i in range(0,len(jcbList)-1):
for j in range(i+1,len(jcbList)):
if jcbList[i].cputime > jcbList[j].cputime :
jcbList[i],jcbList[j] = jcbList[j],jcbList[i]
return jcbList
def sort_HRRN(jcbList,count): #每次执行完上一个作业,对剩余作业排序,响应比作为优先级,优先级高的排前面
#优先级=(等待时间+cputime)/cputime 这里的等待时间可以理解为就是时间量T,因为参与排序的肯定是还没执行的作业
#先计算待处理的作业的优先级,将finish的排到最后,并且将优先级最高的排到第一位
for i in jcbList:
i.prior = (count + i.cputime)/i.cputime
for i in range(len(jcbList)-1,0,-1): #finish的转移到尾部,然后只遍历状态为0的
if jcbList[i].state == 2:
continue
if jcbList[i].prior > jcbList[i-1].prior :
jcbList[i], jcbList[i - 1] = jcbList[i-1], jcbList[i]
def FCFS(jcbList): #先来先服务调度算法
count = 0 #时间片0 即指导书中的时间量T0=0
for i in jcbList:
i.state = 1
i.starttime = count #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
count += i.cputime
i.endtime = count
i.state = 2
i.outSituation_FCFS()
Turnaround_time = 0
daiquan_time = 0
for i in jcbList : # 计算平均周转时间
Turnaround_time += i.endtime #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f')%(Turnaround_time/len(jcbList),daiquan_time/len(jcbList)))
def SJF(jcbList): #短作业优先调度算法
count = 0
sort_SJF(jcbList)
for i in jcbList:
i.state = 1
i.starttime = count #每个作业只执行一次,所以不需要像实验一动态优先级算法一样来判断是否是第一次执行
count += i.cputime
i.endtime = count
i.state = 2
i.outSituation_SJF()
Turnaround_time = 0
daiquan_time = 0
for i in jcbList : # 计算平均周转时间
Turnaround_time += i.endtime #完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime/i.cputime
print(('平均周转时间:%.2f'+' 平均带权周转时间%.2f')%(Turnaround_time/len(jcbList),daiquan_time/len(jcbList)))
def HRRN(jcbList): #响应比高者优先调度算法
count = 0
while jcbList[0].state == 0: #只要首部还是0就说明还有作业没执行完
jcbList[0].state = 1
jcbList[0].starttime = count
count += jcbList[0].cputime
jcbList[0].endtime = count
jcbList[0].state = 2
jcbList[0].outSituation_HRRN()
jcbList.append(jcbList[0]) #将完成的作业移到序列尾部
del jcbList[0]
sort_HRRN(jcbList, count)
Turnaround_time = 0
daiquan_time = 0
for i in jcbList : # 计算平均周转时间
Turnaround_time += i.endtime # 完成时间-提交时间,因为排队的时候时间量为0,所以初始化时就当是0
daiquan_time += i.endtime / i.cputime
print(('平均周转时间:%.2f' + ' 平均带权周转时间%.2f') % (Turnaround_time / len(jcbList), daiquan_time / len(jcbList)))
def main():
print("现在是单道批处理系统作业调度模拟程序")
while True :
jcbNum = int(input("输入作业数量(4,8):"))
print("请从以下方法中选择一种进程调度方法")
print("(1)FCFS (2)SJF (3)HRRN (4)退出")
method = int(input())
jcbList = init(jcbNum)
if method == 1 :
FCFS(jcbList)
elif method == 2 :
SJF(jcbList)
elif method == 3 :
HRRN(jcbList)
else:
break
print("")
try:
flag = int(input("输入4退出程序,或者enter进行下一次操作"))
if flag == 4:
break
except:
pass
if __name__ == '__main__':
main()
import random
##这是多道处理系统作业的调度模拟,FCFS(先来先服务)算法。
class JCB :
def __init__(self, id, cputime) :
# id:序号 cputime:作业预计所需时间
self.first = 0 #0代表没有进入过内存执行,进入了就加一
self.id = id
self.prior = 0 #可作为HRRN中需要的优先级,一开始为0,随着调度、等待而改变;
self.cputime = cputime
self.state = 0 # 0表示Wait 1表示Run 2表示Finish
self.arrivetime = id
self.starttime = 0 #进程开始运行的时间
self.endtime = 0 #进程结束运行时间
self.io = random.randint(1,cputime-1)
self.restoftime = cputime
def out_init(self):
print(("初始化JCB序列:%-2d" + " 到达时间:%-2d"+ " 预计所需时间:%-2d" +" io所在时间片:%-2d")%
(self.id,self.arrivetime,self.cputime,self.io))
def outSituation_FCFS(self) : #输出FCFS法作业调度运行情况
Turnaround = self.endtime - self.id
Daiquan = Turnaround / self.cputime
print(("FCFS: " + "作业:%-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(3, 20)))
# 将随机产生的n个作业保存,创建id和预计CPU时间
print("刚生成的各进程")
for i in jcbList: #输出最开始时进程情况
i.out_init()
return jcbList
def FCFS(jcbList):
#这个系统可以同时处理3个作业,只有一个io,只要当前时间有wait的作业并且执行的作业不满3,就执行新的进程
#如果io冲突,就让争用的作业就等待,并导入下一个进程,如果io结束,就暂停下一个进程,继续执行上一个作业
#忽略调度程序的时间
count = 0
run_list = [] #len(run_list) <= 3
while True :
io_flag = 0 # 为0说明没有被使用,每次也只用一个时间片,所以每次开始都是0
if len(run_list)<3 and jcbList[0].id <= count:
if jcbList[0].state == 0 :
run_list.append(jcbList[0])
del jcbList[0]
run_list[-1].state = 1
if run_list[-1].first == 0 :
run_list[-1].starttime = count
run_list[-1].first += 1
if len(run_list) >0 :
for i in run_list:
if i.io + i.starttime == count :
i.restoftime += 1
if io_flag == 0:
io_flag = 1
else:
i.restoftime += 1
i.io += 1
if jcbList[0].first == 0 :
jcbList[0].starttime = count+1
jcbList[0].first +=1
if jcbList[0].io!=1:
jcbList[0].restoftime -= 1
elif len(jcbList)>1:
if jcbList[1].first == 0:
jcbList[1].starttime = count
jcbList[1].first += 1
jcbList[1].restoftime -= 1
for i in run_list:
if i.restoftime == 0:
i.state = 2
i.endtime = count
jcbList.append(i)
run_list.remove(i)
else:
i.restoftime -= 1
if (len(run_list) == 0) :
break
count += 1
for i in jcbList :
i.outSituation_FCFS()
def main():
print("现在是多道批处理系统作业调度模拟程序")
while True :
jcbNum = int(input("输入作业数量(4,8):"))
print("请从以下方法中选择一种进程调度方法")
print("(1)FCFS (2)退出")
method = int(input())
jcbList = init(jcbNum)
if method == 1 :
FCFS(jcbList)
elif method == 2 :
break
print("")
try:
flag = int(input("输入4退出程序,或者enter进行下一次操作"))
if flag == 4:
break
except:
pass
if __name__ == '__main__':
main()