完整代码传送门
Python模拟先来先服务(FCFS)短进程优先(SJF)调度算法代码
相关文章
原理与内容
1、构建PCB
在多道程序并发执行的环境中,为了保证每个并发执行的程序都可以独立的运行,引入了进程。操作系统为了控制和管理进程,需要为进程配置一个专门的数据结构,这个数据结构用于描述进程的基本情况和执行过程,该数据结构成为进程的控制块PCB。
为了方便模拟各种进程调度算法,该项目中定义的进程控制块PCB应包括进程名称,进程到达(提交请求)的时间,需要服务的时间(执行时间),开始执行的时间,还需要执行的时间,进程完成时间,进程优先级,进程的状态等进程信息,以及用于分析调度算法性能的进程周转时间(等待时间+执行时间)和进程的带权周转时间。具体的PCB数据结构定义如下:
2、进程队列的构建可采用结构体数组,也可以采用链表或者队列的方式来构建。
3、进程状态
WFA:进程还未到——所有非零时刻到达的进程执行前的初始状态
Ready:进程到达后处于就绪状态,等待CPU资源
Running:进程处于运行态
Finish:进程执行结束
4、调度算法原理
(1)先来先服务(FCFS)调度算法
该算法是指在进程调度时,系统按照进程到达的先后顺序来进行调度,即优先考虑在系统中等待时间最久的进程,该调度算法不考虑进程的执行时间。每次调度,从就绪队列中选择等待最久的进程,为其分配CPU,直到该进程阻塞或结束后,才切换其他进程。
(2)短进程优先(SPF)调度算法
该算法是指在进程调度时,系统按照进程需要的执行时间长短来进行调度,优先选择需要执行时间短的进程。该调度算法不考虑进程的等待时间。每次调度,从就绪队列中选择需要执行时间最短的进程,为其分配CPU,直到该进程阻塞或结束后,才切换下一个执行时间最短的进程。
(3)优先级(HPF)调度算法
每个进程都有一个与进程相关的优先级,具有最高优先级的进程优先分配到CPU,同优先级的进程按照FCFS的顺序调度。
优先级调度算法有抢占式优先级调度算法和非抢占式优先级调度算法。
抢占式优先级调度算法,是当有新的高优先级的进程到达时,进程需要切换到新到达的高优先级进程。
非抢占式优先级调度算法,是指当有新的高优先级进程到达时,进程不发生切换,当原进程执行结束或变为阻塞时,才切换到新的高优先级进程。
(4)时间片轮转(RR)调度算法
该算法类似FCFS调度,但增加了抢占来切换进程,首选需要选择一个较小的时间单元作为时间片(时间量)。时间片大小通常为10~100ms,就绪队列作为进程的FIFO的循环队列,新进程添加到就绪队列尾部,调度时,从就绪队列中选择第一个进程,为每个进程分配不超过一个时间片的CPU,若进程需要执行时间小于时间片,进程结束后自动释放CPU,调度程序接着处理就绪队列的下一个进程;若进程需要执行时间大于一个时间片,进程执行一个时间片后,定时器中断,进程切换,原进程添加到就绪队列的尾部,调度程序选择就绪队列中的下一个进程。
(5)高响应比(HPF)调度算法
引入响应比的概念,响应比=(进程的等待时间+执行时间)/执行时间=1+等待时间/执行时间。
进程调度时,需要计算每个进程的响应比,然后从就绪队列中选择响应比最高的进程为其分配CPU。该算法既考虑进程的等待时间又考虑进程的执行时间。
过程与结果
声明PCB类及参数,初始化参数,包括进程数、及两个类列表(进程列表、等待列表),因为python没有“结构体”的申明,因此以类来进行进程调度单位的模拟
图1 初始化参数及PCB类声明
输入进程数Num,初始化类列表长度,并循环输入基本数据,后进入Menu()进行用户交互
图2 主代码
图3 Menu( )
先来先服务FCFS
运用.sort( )以 arrivalTime(到达时间)为权重进行排序输出
图4 函数FCFS( )代码
图5 函数FCFS( )流程图
短进程优先SJF
以serviceTime(运行时间)为权重,以w传参进行对部分序列进行排序操作,以参数w、nowtime为数据节点进行SJF的判断操作
图6 函数SJF( )代码
图7 函数SJF( )流程图
图8、9 代码执行结果
图10 代码执行流程图
-
部分代码示例
class PCB:
def __init__(self):
self.name = ""
self.arrivalTime = 0
self.serviceTime = 0
self.startTime = 0
self.endTime = 0
self.turnaroundTime = 0
self.weightTuraroundTime = 0
self.status = 0
def FCFS(Num):
# 以到达时间为权重排序
pcb.sort(key=lambda x: x.arrivalTime)
pcb[0].startTime = pcb[0].arrivalTime
pcb[0].endTime = pcb[0].startTime + pcb[0].serviceTime
pcb[0].turnaroundTime = pcb[0].endTime - pcb[0].arrivalTime
pcb[0].weightTuraroundTime = pcb[0].turnaroundTime/(1.00*pcb[0].serviceTime)
for i in range(Num) :
if pcb[i].arrivalTime > pcb[i-1].endTime:
pcb[i].startTime = pcb[i].arrivalTime
else:
pcb[i].startTime = pcb[i-1].endTime
pcb[i].endTime = pcb[i].startTime + pcb[i].serviceTime
pcb[i].turnaroundTime = pcb[i].endTime - pcb[i].arrivalTime
pcb[i].weightTuraroundTime = pcb[i].turnaroundTime/(1.00*pcb[i].serviceTime)
print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
print("进程名 提交时间 运行时间 开始时间 完成时间 周转时间 带权周转时间")
for i in range(Num):
print(pcb[i].name, " ", pcb[i].arrivalTime, " ",pcb[i].serviceTime , " ",pcb[i].startTime,
" ", pcb[i].endTime, " ", pcb[i].turnaroundTime, " ", pcb[i].weightTuraroundTime)
def sortstime(wait, n):
# 以传参来对部分列表进行简单排序
for i in range(1,n):
for j in range(n-i):
if wait[j].serviceTime > wait[j+1].serviceTime:
wait[j], wait[j+1] = wait[j+1], wait[j]
def SJF(Num):
count, flag , nowtime, w= Num, 0, 0.0, 0
print("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
print("进程名 提交时间 运行时间 开始时间 完成时间 周转时间 带权周转时间")
while count > 0:
for i in range(Num):
if pcb[i].arrivalTime <= nowtime and pcb[i].status == 0:
pcb[i].status = 1 # 进入等待
wait[w] = pcb[i]
w = w + 1
sortstime(wait, w) # 传参w,处理0,w的排序
count = count - 1
flag = 1
if w > 0:
for i in range(-1,w):
if wait[0].status == 1:
wait[0].startTime = nowtime
wait[0].endTime = wait[0].startTime + wait[0].serviceTime
wait[0].turnaroundTime = wait[0].endTime - wait[0].arrivalTime
wait[0].weightTuraroundTime = wait[0].turnaroundTime/(1.00*wait[0].serviceTime)
nowtime = wait[0].endTime
print(wait[0].name, " ", wait[0].arrivalTime, " ",wait[0].serviceTime , " ",wait[0].startTime,
" ", wait[0].endTime, " ", wait[0].turnaroundTime, " ", wait[0].weightTuraroundTime)
for j in range(w):
wait[j] = wait[j + 1] # 往后查询
w = w - 1
if flag == 0:
nowtime = nowtime + 1
flag = 0
for i in range(Num):
pcb[i].status = 0
nowtime = 0