操作系统——多级反馈队列调度系统

本文介绍了一种使用Python和FastAPI实现的多级反馈队列调度算法,用户可以通过输入队列参数和进程信息进行模拟。程序能计算进程的运行时间、周转时间和带权周转时间,并动态演示进程状态和队列运行情况。在调试过程中解决了抢占和队列管理的问题,提供了准确的调度算法实现和结果分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、课程设计的主要内容

模拟实现多级反馈队列调度算法,要求设置不少于5个反馈队列,并通过菜单输入反馈队列的个数、优先级、时间片长度,以及其他补充的参数(加分项)。
要求完成以下功能:
(1)输入各个进程的进入时间和估计运行时间。
(2)计算各个进程的开始时间、结束时间、周转时间、带权周转时间,平均周转时间、平均带权周转时间,并直观输出显示。
(3)要求动态演示各个进程的运行情况状态,以及各个队列的运行情况。

二、需求分析

1、模拟实现多级反馈队列调度算法,要求设置不少于5个反馈队列,并通过菜单输入反馈队列的个数、优先级、时间片长度

多级反馈队列运行情况如下所示:
在这里插入图片描述
多级反馈队列算法:
设置多个就绪队列,分别赋予不同的优先级,如逐级降低,每个队列时间片长度也不同,优先级越低则时间片越长,如逐级加倍,新进程进入内存后,先投入队列1的末尾,按FCFS算法调度。若按队列1一个时间片未能执行完,则降低投入到队列2的末尾,同样按FCFS算法调度。如此下去,降低到最后的队列,则按"时间片轮转"算法调度直到完成。
仅当较高优先级的队列为空,才调度较低优先级的队列中的进程执行,如果进程执行时有新进程进入较高优先级的队列,则抢先执行新进程,并把被抢占的进程投入原队列的末尾。

2、输入各个进程的进入时刻和估计运行时间

各个进程的进入时刻和估计运行时时间用于后续多级反馈队列调度算法使用。

3、计算各个进程的开始时间、结束时间、周转时间、带权周转时间,平均周转时间、平均带权周转时间,并直观输出显示

周转时间=作业完成时刻—作业到达时刻;
带权周转时间=周转时间/服务时间;
平均周转时间=作业周转总时间/作业个数;
平均带权周转时间=带权周转总时间/作业个数;
所以首先要通过多级反馈队列算法对所有的作业进行调度,计算出作业完成时刻才能够计算出相应的周转时间以及带权周转时间。

4、动态演示各个进程的运行情况状态,以及各个队列的运行情况

动态演示可以帮助我们直观地了解进程的运行情况和队列的状态。通过观察动态演示结果,我们可以判断调度算法是否合理,并根据需要进行改进。

三 、概要设计

1、模块设计

整个程序被分为以下三个模块:
数据输入模块:
可视化界面提示用户输入,将用户输入的信息发送到后端进行处理
多级反馈队列调度算法执行模块:
最主要的部分,接受用户输入数据,进行相关处理后用于执行多级反馈队列算法
结果显示模块:
将结果直观输出显示

2、模块关系

在这里插入图片描述

四 、详细设计

1、实验原理分析设计

对于多级反馈队列,根据用户输入的队列信息按照优先级的逆序对队列进行排序,即进程首先被分配到优先级高的运行。并为前n-1(若有n个队列)个添加标识符为1的属性,表明如果该队列时间片用完后,进程剩余时间大于0,则将进程加入到下一级队列的队尾,第n个队列标识符为0,表示如果该队列时间片用完后,进程剩余时间大于0,则将进程加入到该队列的队尾。多级反馈队可抢占的特性的实现,是将用户输入的各个进程的进入时间添加一个列表存储,表示在这些时刻有可能会发生抢占。当进程在队列中运行时,首先会判断该进程在该队列时间片内运行时是否可能发生抢占,如果不会发生抢占,则“大胆”的运行,如果会发生抢占就“小心谨慎”的运行。
在这里插入图片描述

2、程序输入输出分析设计

对于程序输入输出,采用Fastapi框架,用两个页面实现:
数据输入界面如下:
在这里插入图片描述
结果输出界面如下:
在这里插入图片描述

五 调试分析

1、抢占问题

抢占时刻下一秒,被抢占的进程是没有运行的,而是直接添加到运行时的队列的队尾,在前期运行时,未考虑到此情况,导致算的结果有误差:
错误结果:
在这里插入图片描述
改进后的正确结果:
在这里插入图片描述
抢占后未将可能抢占的时间从存储可能抢占时间的列表中删除,导致死循环,后经改进解决了此问题。

2、队列问题

在进程未运行完需要加入下一队列时未考虑好最低级队列导致地址越界:
在这里插入图片描述
后经过改进解决了此问题。

六 测试结果

1、结果分析

队列信息:
在这里插入图片描述

进程信息:
在这里插入图片描述

抢占时运行情况:
在这里插入图片描述

自行分析:
在这里插入图片描述

经反复分析验证,运行结果无误。
七 用户使用说明
启动支持python的编译器,安装相关环境,打开源程序,运行。访问浏览器访问:http://127.0.0.1:8000 打开网页如下:
如图所示操作,点击提交按钮:
在这里插入图片描述

结果显示如图:
在这里插入图片描述

动态运行情况在编译器终端显示:

在这里插入图片描述

八 课程设计总结

在本次实验中,我成功地模拟实现了多级反馈队列调度算法,并完成了实验要求的各项功能,包括输入进程信息、计算各个进程的运行时间和指标,以及动态演示进程的运行情况和队列的状态。以下是我对实验的一些心得和体会:
深入理解调度算法原理:在开始实验之前,我仔细学习了多级反馈队列调度算法的原理和实现方式。理解了各个队列的优先级和时间片长度的设置对进程调度的影响。
设计合理的用户界面:为了方便输入队列参数和进程信息,我设计了一个简单的菜单界面。通过菜单输入方式,用户可以灵活设置队列的个数、优先级、时间片长度等参数。这样的设计提高了实验的可定制性和易用性。
准确计算运行指标:根据输入的进程信息和队列参数,我实现了计算各个进程的开始时间、结束时间、周转时间和带权周转时间的功能。通过这些指标,我能够评估调度算法的性能,并对比不同设置下的结果。确保计算准确性对于实验的结果分析和结论的正确性至关重要。
动态演示增强可视化效果:实验要求实现动态演示功能,我将运行情况打印在终端展示进程的运行情况和队列的调度情况。这种方式更直观地展示了进程的状态和队列的运行情况,使实验结果更易于理解和分析。动态演示对于展示调度算法的效果和改进空间有着重要的作用。
通过本次实验,我对多级反馈队列调度算法有了更深入的了解,并成功地实现了模拟。我认识到合理的算法设计、准确的计算和直观的结果展示是实验中的关键要素。实验过程中,我锻炼了问题分析和解决的能力,并学会了如何利用实验结果来评估算法性能和进行改进。这对于进一步深入学习操作系统和进程调度算法有着重要的意义。

代码

main.py

import uvicorn
import time
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

"""
周转时间=作业完成时刻—作业到达时刻;

带权周转时间=周转时间/服务时间;

平均周转时间=作业周转总时间/作业个数;

平均带权周转时间=带权周转总时间/作业个数;
"""

app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

# 首页路由
@app.get("/")
def index(request: Request):
    return templates.TemplateResponse("index.html", {
   "request": request})

# 处理表单提交
@app.post("/process_form")
async def process_form(request: Request):
    form_data = await request.form()
    queue_count = int(form_data["queueCount"])
    process_count = int(form_data["processCount"])
    # 创建一个空列表,用于存储队列
    queues = []
    # 使用循环创建指定数量的队列
    for i in range(queue_count):
        priority = int(form_data[f"priority_{
     i}"])
        time_slice = int(form_data[f"time_slice_{
     i}"])
        queue = {
   "优先级": priority, "时间片": time_slice, "标记位": 1}  # 创建一个包含优先级、时间片和标记位属性的字典
        queues.append(queue)  # 将队列添加到列表中
    # 对队列列表按优先级从高到低进行排序
    queues.sort(key=lambda x: (-x["优先级"], x["时间片"]))
    # 为队列中的每个字典添加队列标号
    for i, queue in enumerate(queues):
        queue["队列标号"] = i + 1
    # 将最后一个队列的标记位置为0,表示该队列不能将进程加载到下一队列中
    if queues:
        queues[-1]["标记位"] = 0
    # 打印创建的队列
    for queue in queues:
        print(f"队列{
     queue['队列标号']}: {
     queue}")
    # 创建一个空列表,用于存储所有的进程
    jincheng = []
    #用于存储可能的抢占时间
    qiangzhanshijian =[]
    # 使用循环创建指定数量的进程
    for i in range(process_count):
        enter_time = int(form_data[f"arrival_time_{
     i}"])
        runtime = int(form_data[f"run_time_{
     i}"])
        qiangzhanshijian.append(enter_time)
        dictionary = {
   
            "进程": i + 1,
            "进入时刻": enter_time,
            "估计运行时间": runtime,
            "剩余运行时间": runtime,
            "开始时刻": 0,
            "结束时刻": 0,
        }  # 创建一个包含进入时刻、估计运行时间、开始时刻、结束时刻和标记位属性的字典
        jincheng.append(dictionary)  # 将字典添加到列表中

    print(f"可能的抢占时间: {
     qiangzhanshijian}")
    # 打印创建的进程
    for i, dictionary in enumerate(jincheng):
        print(f"进程{
     i + 1}: {
     dictionary}")
    # 创建一个空列表,用于存储满足进入时刻条件的字典
    filtered_jincheng = [[] for _ in range(queue_count)]
    shijian = 0 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谭你一个脑瓜崩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值