python 3.0 实现多级反馈队列进程调度算法



前言

写的很拉,但是可以实现多级反馈调度的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,临时学的(太菜了,呜呜呜)

第八版

#解决随机生成进程名会重复的问题

# 细节完善
# 多测试几个样例

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)

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值