一、 实验目的
用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。
二、 例题
为单道批处理系统设计一个作业调度程序。
由于在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
作业调度算法:采用先来先服务(FCFS)调度算法,即按作业提交的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。各个等待的作业按照提交时刻的先后次序排队,总是首先调度等待队列中队首的作业。每个作业完成后要打印该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后要计算并打印这组作业的平均周转时间、带权平均周转时间。
调度算法的流程图如下 :
三、 实验要求
1、 编写并调试一个单道处理系统的作业等待模拟程序。
作业等待算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRN)的调度算法。
对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间,以比较各种算法的优缺点。
2、 编写并调度一个多道程序系统的作业调度模拟程序。
作业调度算法:采用基于先来先服务的调度算法。可以参考课本中的方法进行设计。
对于多道程序系统,要假定系统中具有的各种资源及数量、调度作业时必须考虑到每个作业的资源要求。
3、 编写并调试一个多道程序系统的作业调度模拟程序。
作业调度算法:采用基于优先级的作业调度。
可以参考课本中的例子自行设计。
用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。
①实验内容
为单道批处理系统设计一个作业调度程序。
由于在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。
作业调度算法:采用先来先服务(FCFS)调度算法,即按作业提交的先后次序进行调度。总是首先调度在系统中等待时间最长的作业。每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。
作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。各个等待的作业按照提交时刻的先后次序排队,总是首先调度等待队列中队首的作业。每个作业完成后要打印该作业的开始运行时刻、完成时刻、周转时间和带权周转时间,这一组作业完成后要计算并打印这组作业的平均周转时间、带权平均周转时间。
②实验要求
编写并调试一个单道处理系统的作业等待模拟程序。
作业等待算法:分别采用先来先服务(FCFS),最短作业优先(SJF)、响应比高者优先(HRN)的调度算法。
对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间,以比较各种算法的优缺点。
想要完成操作系统算法,首先要弄清楚操作系统相关的专业术语。弄清各个算法的流程和目的要求。才能模拟出相关算法的过程。
在我的理解中,
FCFS算法:
优先考虑系统中等待时间长的作业,而不管该作业所需执行时间长短。说的通俗点 , 哪个作业先提交 , 哪个作业先进内存。这是对作业调度而言,同样,FCFS算法也可以用于进程调度,此时谁先进内存的谁先上CPU。
那么这样一来就会出现这样的问题:如果一个作业所需运行时间很长(长作业) , 并且它先提交给系统。那么该作业就要长时间的占用CPU,而之后来到的短作业 , 即便它占用cpu的时间很短也上不了CPU。在单位时间内, CPU上执行的作业数会变少,系统吞吐量降低。
为了解决这种情况,采用SJF算法。
SJF算法:
优先考虑短作业,即:不管作业的提交时间,作业服务时间短的先上CPU。这样一来,系统吞吐量提高了。
HRN算法:
FCFS可能造成短作业用户不满,SPF可能使得长作业用户不满,于是提出HRN,选择响应比最高的作业运行。响应比=1+作业等待时间/作业处理时间。
基本概念:
作业周转时间=完成时间-提交时间
作业平均周转时间=周转时间/作业个数
作业带权周转时间=周转时间/运行时间
响应比=(等待时间+运行时间)/运行时间
①FCFS算法:
②SJF算法:
③hrn算法:
通过本次实验,我深刻的理解了操作系统中作业资源的分配方式和作业的调度方式及相关的3种算法。操作系统实验重在理解每一个算法的意图和目的,那么就选择适当的数据结构模拟过程就可以完成相关算法了。
先来先服务的作业调度,实现最简单。
最高响应比优先作业调度,既照顾了短作业,又照顾了作业到来的顺序,不会使长作业长期得不到运行,但是每次调度下一个作业前要计算剩余到来作业的响应比,增加了系统的开销。
开始时对作业调度不是很那么地清晰,通过做这个实验,现在对操作系统的作业调度有了清晰的理解,感觉在这个过程中自己就是充当了调度员的角色。
本次实验采用python完成,IDE是pycharm,python的queue库文件很好的支持了我在优先权算法中对队列的相关操作,python的operator库文件,很好的提供了基于类的属性按值排序的功能,这些在算法的编写过程中否起到了很大的作用。
import operator
import random
import queue
Q = queue.Queue() # 定义队列
arr_jcb = []
ID = ['A', 'B', 'C', 'D']
T = 0
A=0
B=0
class JCB:
def __init__(self, id, arriveTime, requestTime, startTime, finishTime, turnaroundTime, W_turnaroundTime, status):
self.id = id # 进程的id
self.arriveTime = arriveTime # 到达时间
self.requestTime = requestTime # 所需运行的时间
self.startTime = startTime # 开始时间
self.finishTime = finishTime # 结束时间
self.turnaroundTime = turnaroundTime # 周转时间
self.W_turnaroundTime = W_turnaroundTime # 带权周转时间
self.status = status # 状态
self.ono = 0 # 响应比
def func():
node = Q.get()
if node.arriveTime > T:
node.startTime = node.arriveTime
else:
node.startTime = T
node.finishTime = node.startTime + node.requestTime
node.turnaroundTime = node.finishTime - node.arriveTime
node.W_turnaroundTime = node.turnaroundTime / node.requestTime
node.status = 'finish'
print('***执行算法***')
for item in arr_jcb:
print('进程{} 到达时间:{} 运行时间:{} 开始时间:{} 结束时间:{} 周转时间:{} 带权周转时间:{} 状态:{}'.format(item.id, item.arriveTime,item.requestTime, item.startTime,item.finishTime,item.turnaroundTime,item.W_turnaroundTime, item.status,item.status))
return node.finishTime
for i in range(0, 4):
arriveTime = random.randint(1, 10) # 随机生成到达时间
requestTime = random.randint(1, 20) # 随机生成需要时间
jcb = JCB(ID[i], arriveTime, requestTime, 0, 0, 0, 0, 'wait')
jcb.ono=arriveTime/requestTime+1
arr_jcb.append(jcb)
print('1、先来先服务算法fcfs算法\t2、最短作业优先算法sjf\t3、最高响应比优先算法hrn')
key = int(input('请输入需要使用的算法编号:'))
if key==1:
print('**********初始化生成4个进程**********')
for item in arr_jcb:
print('进程{} 到达时间:{} 运行时间:{} 开始时间:{} 结束时间:{} 周转时间:{} 带权周转时间:{} 状态:{}'.format(item.id, item.arriveTime,item.requestTime, item.startTime,item.finishTime,item.turnaroundTime,item.W_turnaroundTime, item.status,item.status))
arr_jcb.sort(key=operator.attrgetter('arriveTime')) # 按照状态优先权重的值升序排列
for item in arr_jcb:
Q.put(item)
arr_jcb.sort(key=operator.attrgetter('id')) # 按照状态优先权重的值升序排列
for item in arr_jcb:
T = func()
print('***总结***')
for item in arr_jcb:
A += item.turnaroundTime
B += item.W_turnaroundTime
print('本次fcfs算法,平均周转时间:', A / 4, '平均带权周转时间:', B / 4)
elif key==2:
print('**********初始化生成4个进程**********')
for item in arr_jcb:
print('进程{} 到达时间:{} 运行时间:{} 开始时间:{} 结束时间:{} 周转时间:{} 带权周转时间:{} 状态:{}'.format(item.id, item.arriveTime,item.requestTime, item.startTime,item.finishTime,item.turnaroundTime,item.W_turnaroundTime, item.status,item.status))
arr_jcb.sort(key=operator.attrgetter('requestTime')) # 按照状态优先权重的值升序排列
for item in arr_jcb:
Q.put(item)
arr_jcb.sort(key=operator.attrgetter('id')) # 按照状态优先权重的值升序排列
for item in arr_jcb:
T = func()
print('***总结***')
for item in arr_jcb:
A += item.turnaroundTime
B += item.W_turnaroundTime
print('本次sjf算法,平均周转时间:', A / 4, '平均带权周转时间:', B / 4)
elif key==3:
print('**********初始化生成4个进程**********')
for item in arr_jcb:
print('进程{} 到达时间:{} 运行时间:{} 开始时间:{} 结束时间:{} 周转时间:{} 带权周转时间:{} 状态:{}'.format(item.id, item.arriveTime,item.requestTime, item.startTime,item.finishTime,item.turnaroundTime,item.W_turnaroundTime, item.status,item.status))
arr_jcb.sort(key=operator.attrgetter('ono')) # 按照响应比的值升序排列
for item in arr_jcb:
Q.put(item)
arr_jcb.sort(key=operator.attrgetter('id')) # 按照状态优先权重的值升序排列
for item in arr_jcb:
T = func()
print('***总结***')
for item in arr_jcb:
A += item.turnaroundTime
B += item.W_turnaroundTime
print('本次hrn算法,平均周转时间:', A / 4, '平均带权周转时间:', B / 4)