前言
写的很拉,但是可以实现多加反馈调度的python3.0代码
算法参考:「土豆洋芋山药蛋」作者的文章,说实话,这个写的真的不咋地,但是他给我一个参考,哈哈。
他文章的缺点:
1.没有实现进程的随机生成,不能实现抢占
2.周转时间计算错误
进程一开始随机抵达的时间是 arrive time,而不是在最后一个队列集体设置arrive time,并以这个标准计算周转时间
多级反馈队列调度算法(附Python3实现代码)_土豆洋芋山药蛋的博客-CSDN博客_多级反馈队列调度算法实现
一、操作系统课程设计任务
1.设计进程控制块PCB表结构,适用于多级反馈队列调度算法。
PCB结构通常包括以下信息:进程名,进程优先数,轮转时间片,进 程已占用的CPU时间,进程还需要的CPU时间,进程的状态,当前队列指针等。
2.建立3个进程就绪队列,分别设置不同的时间片和优先级。
3.编制进程调度算法,实现该算法的模拟
4.使用开发工具设计可视化界面(这个可视化是组员做的,就省略拉,用的pyqt)
二、具体实现
1.多级反馈定义
1、进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。
2、首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。
3、对于同一个队列中的各个进程,按照FCFS分配时间片调度。比如Q1队列的时间片为N,那么Q1中的作业在经历了N个时间片后若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列末尾,直至完成。
4、在最后一个队列QN中的各个进程,按照时间片轮转分配时间片调度。
5、在低优先级的队列中的进程在运行时,又有新到达的作业,运行完这个时间片之后,然后立即把处理机分给高优先级进程。(抢占式)。
(ps:关于抢占式的定义,网上有两种,我自己随便挑了一个写的,就是上面的第5点)
2.代码
因为之前没学过python,临时学的,所以实际上我一共写了8版,才最后完善(太菜了,呜呜呜)
第八版
#解决随机生成进程名会重复的问题
# 细节完善
# 多测试几个样例
import operator
import random
# 保证第一个进程到达时,当前运行时间与第一个进程相同
flag = 1
# 进程控制块PCB结构
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.finish_time = 0 # 完成时间
self.cycling_time = 0 # 周转时间
self.w_cycling_time = 0 # 带权周转时间
# 就绪队列
class Queue:
def __init__(self, level, process_list):
self.level = level
self.process_list = process_list
self.q = 0
def size(self): # 返回当前队列大小
return len(self.process_list)
def get(self, index): # 返回指定位置进程
return self.process_list[index]
def add(self, process): # 添加新的进程
self.process_list.append(process)
def delete(self, index): # 删除进程
self.process_list.remove(self.process_list[index])
# def check(queue_list,i,running_time,flag):
def check(queue_list, i, running_time):
# 从第一就绪队列开始检查
for j in range(i):
index = int(0)
currentQueue = queue_list[j]
if (currentQueue == []):
# 如果队列没有进程则直接下一个 !!!
print('第%d就绪队列为空' % j)
continue
else:
# for k in range (currentQueue.size()): 中currentQueue.size()的值不能动态变化 !!!
# 出现交叉情况之后数组长度会增长
# 这就意味着在这过程中被加入当前就绪队列的进程没有被执行,check()就已经回退
for k in range(currentQueue.size()):
# 如果本就绪队列最快要执行的进程此时没有到达,此队列之后的进程不用检查
if (currentQueue.get(index).arrive_time > running_time):
print('运行时间 %d,%s 没有抵达' % (running_time, currentQueue.get(index).name))
break
else:
print('运行时间 %d,%s 已经抵达' % (running_time, currentQueue.get(index).name))
if currentQueue.get(index).left_serve_time > queue_list[j].q:
# 考虑到第0列和第1列 arrive time可能出现交叉的情况
# 即进程在第三就绪队列执行的时候,先检查第一就绪队列是否有已到达的进程
# 检查第二就绪队列每一进程之前,也应该考虑当前第一就绪队列是否有形的进程到达
# ***
if i == 2 and j == 1:
running_time = check(queue_list, j, running_time)
currentQueue.get(index).left_serve_time -= queue_list[j].q
running_time += queue_list[j].q
# print('第 %d 队列时间片: %d' % (i, q_list[i].q))
# 容易搞错i,j
# check()中 j 代表的是当前就绪队列
if j == len(queue_list) - 1:
queue_list[j].add(currentQueue.get(index))
print('进程没有执行完毕,需要添加至第 %d 队列末尾:进程名称:%s ' % (j, currentQueue.get(index).name))
else:
queue_list[j + 1].add(currentQueue.get(index))
print('进程没有执行完毕,需要添加至第 %d 队列末尾:进程名称:%s ' % (j + 1, currentQueue.get(index).name))
elif currentQueue.get(index).left_serve_time == queue_list[j].q:
running_time += queue_list[j].q
print('服务完成并弹出:', currentQueue.get(index).name)
currentQueue.get(index).left_serve_time = 0
else:
running_time += currentQueue.get(index).left_serve_time
print('服务完成并弹出:', currentQueue.get(index).name)
currentQueue.get(index).left_serve_time = 0
# 已完成
if currentQueue.get(index).left_serve_time == 0:
# 计算完成时间
currentQueue.get(index).finish_time = running_time
# 计算周转时间
currentQueue.get(index).cycling_time = currentQueue.get(index).finish_time - currentQueue.get(
index).arrive_time
# 计算带权周转时间
currentQueue.get(index).w_cycling_time = float(
currentQueue.get(index).cycling_time) / currentQueue.get(index).serve_time
# 打印
print('%s 进程已完成的进程,详细信息如下:' % currentQueue.get(index).name)
print('进程名称:%s ,完成时间: %d ,周转时间:%d ,带权周转时间: %.2f' % (
currentQueue.get(index).name, currentQueue.get(index).finish_time,
currentQueue.get(index).cycling_time,
currentQueue.get(index).w_cycling_time))
# index -= 1
# 对于已完成的进程:有进程完成任务后,index先回退,之后再加,以保持指向下一个需要调度的进程
# 对于未完成的进程:先添加到下一就绪队列,再从当前就绪队列删除 !!!
# ***
currentQueue.delete(index)
# index += 1
# print('第%d 列大小%d' % ( i,currentQueue.size()))
if index == currentQueue.size():
break
return running_time
# 多级反馈调度算法
def MulitlevedFeedbackQueue(queue_list, queue_first, rt):
q_list = queue_list # 当前队列集合
q_first = queue_first # 第一个队列的时间片
running_time = rt
# running_time = int(0)
for i in range(len(q_list)):
# 确定每个队列的时间片
if i == 0:
q_list[i].q = q_first
else:
q_list[i].q = q_list[i - 1].q * 2
currentQueue = q_list[i]
index = int(0)
global flag # 声明全局变量
# 第一个进程到达时间 不 默认 为 0
if flag:
running_time = currentQueue.get(0).arrive_time
flag = 0
# *** 解决3个就绪队列当前均无可执行进程,但是第一就绪队列仍有进程没有抵达的问题
if currentQueue.size() == 0:
print('此时本就绪队列为空')
# 若第一就绪队列无等待进入的进程,则执行完毕,退出
if q_list[0].size() != 0:
MulitlevedFeedbackQueue(queue_list, queue_first, q_list[0].get(0).arrive_time)
else:
# 从第一个队列开始执行时间片
# 先判断是否是最后一个队列,最后一个队列加入到当前队列的尾部
# 不是最后一个队列的话,就执行当前队列时间片后判断是否有必要加入到下一个队列的末尾
while (True):
# print('第 %d 队列,进程名称:%s ' % (i, currentQueue.get(index).name))
# 到达时间越小 代表越先到达
if currentQueue.get(index).arrive_time > running_time:
# print('运行时间 %d,%s 没有抵达' % (running_time, currentQueue.get(index).name))
break
else:
if (i != 0):
running_time = check(queue_list, i, running_time)
# *** 第二次check 解决 出现交叉情况之后数组长度会增长 ,check()函数会遗留可以执行的优先级更高的进程问题
running_time = check(queue_list, i, running_time)
if currentQueue.get(index).left_serve_time > q_list[i].q:
currentQueue.get(index).left_serve_time -= q_list[i].q
running_time += q_list[i].q
# print('第 %d 队列时间片: %d' % (i, q_list[i].q))
if i == len(queue_list) - 1:
queue_list[i].add(currentQueue.get(index))
print('进程没有执行完毕,需要添加至第 %d 队列末尾:进程名称:%s ' % (i, currentQueue.get(index).name))
else:
queue_list[i + 1].add(currentQueue.get(index))
print('进程没有执行完毕,需要添加至第 %d 队列末尾:进程名称:%s ' % (i + 1, currentQueue.get(index).name))
elif currentQueue.get(index).left_serve_time == q_list[i].q:
running_time += q_list[i].q
print('服务完成并弹出:', currentQueue.get(index).name)
currentQueue.get(index).left_serve_time = 0
else:
running_time += currentQueue.get(index).left_serve_time
print('服务完成并弹出:', currentQueue.get(index).name)
currentQueue.get(index).left_serve_time = 0
# 已完成
if currentQueue.get(index).left_serve_time == 0:
# 计算完成时间
currentQueue.get(index).finish_time = running_time
# 计算周转时间
currentQueue.get(index).cycling_time = currentQueue.get(
index).finish_time - currentQueue.get(
index).arrive_time
# 计算带权周转时间
currentQueue.get(index).w_cycling_time = float(
currentQueue.get(index).cycling_time) / currentQueue.get(index).serve_time
# 打印
print('%s 进程已完成的进程,详细信息如下:' % currentQueue.get(index).name)
print('进程名称:%s ,完成时间: %d ,周转时间:%d ,带权周转时间: %.2f' % (
currentQueue.get(index).name, currentQueue.get(index).finish_time,
currentQueue.get(index).cycling_time,
currentQueue.get(index).w_cycling_time))
# index -= 1
# 对于已完成的进程:有进程完成任务后,index先回退,之后再加,以保持指向下一个需要调度的进程
# 对于未完成的进程:先添加到下一就绪队列,再从当前就绪队列删除 !!!
currentQueue.delete(index)
# index += 1
# print('第%d 列大小%d' % ( i,currentQueue.size()))
if index == currentQueue.size():
break
# 随机生成进程
def CreatePcb(queue_list):
process_list0, process_list1, process_list2 =[], [], []
num = random.randint(1, 5)
print('进程数 %d' % num)
name = random.sample('abcdefghijklmnopqrstuvwxyz',num)
for i in range(num):
arrive_time = random.randint(1, 10)
serve_time = random.randint(1, 10)
print('进程名%s 到达时间%d 服务时间%d' % (name[i], arrive_time, serve_time))
process = Process(name[i], arrive_time, serve_time)
process_list0.append(process)
# 按照arrive time进行排序
cmpfun = operator.attrgetter('arrive_time')
process_list0.sort(key=cmpfun)
queue_list = []
queue0 = Queue(0, process_list0)
queue1 = Queue(1, process_list1)
queue2 = Queue(2, process_list2)
queue_list.append(queue0)
queue_list.append(queue1)
queue_list.append(queue2)
return queue_list
'''
测试程序
'''
if __name__ == '__main__':
# 队列
queue_list = []
# 创建就绪队列
cp = CreatePcb(queue_list)
# 执行多级反馈队列调度算法,第一队列时间片为1
mfq = MulitlevedFeedbackQueue(cp, 1, 0)
?
|