【操作系统实验】编制银行家算法通用程序(python)

本文介绍了一种基于银行家算法的死锁避免方案,并通过Python实现了一个交互式的程序来帮助用户理解算法的工作原理。用户可以在图形界面上输入请求资源的进程名和所需资源数,系统则会反馈资源请求的结果及当前的安全状态。
部署运行你感兴趣的模型镜像

实验一、编制银行家算法通用程序,并检测所给状态的系统安全性。假定系统的任何一种资源在任一时刻只能被一个进程使用。任何进程已经占用的资源只能由进程自己释放,而不能由其它进程抢占。进程申请的资源不能满足时,必须等待。

    设计的要求:

        (1)   程序中使用的数据结构及主要符号说明;

        (2)   资源的种类和数目可以变化的

        (3)   进程可以任意的顺序创建和变化


#!/usr/bin/env python
#  -*- coding: utf-8 -*

'''
    该模块实现了银行家算法,可以有效地避免死锁。
    算法思想:
        每一个进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型地最大单元数目
        1) 其数目不应超过系统所拥有地资源总量
        2)当请求资源时,系统必须首先确定是否有足够的资源分配给进程
        3)计算将这些资源分配给进程后,是否会使系统处于不安全状态
    模块功能:
        在用户可视化界面上,用户可以根据自己的需求,输入请求资源的进程名称和进程请求的资源数,
        点击CHECK按钮,系统会提示用户请求资源的结果。其中,资源的种类和数目是可以变化的,进程
        可以任意的创建和变化,资源可以任意的顺序创建和变化。
'''

import numpy as np
import sys
from PyQt5.QtWidgets import QDesktopWidget, QHBoxLayout, QVBoxLayout
from PyQt5.QtGui import QBrush,QPixmap,QPalette,QIcon
from PyQt5.QtWidgets import (QLabel,  QGridLayout)
from PyQt5.QtWidgets import (QWidget, QPushButton, QLineEdit, QApplication)

def safeAlgorithm():
    #安全性检查算法
    global safeList, system_security
    safeList= []
    work = Available
    Finish=[False]*length_progress

    #在进程集合中找到一个 Finish[i] = false 且 need[i,j] < Work[j] 的进程
    while False in Finish:
        for i in range(0,length_progress):
           for j in range(0,length_Avalable):
                if (Finish[i] == False) and (Need[i]<=work).all():
                    for m in range(length_Avalable):
                        work[m] = work[m]+ Allocation[i][m]
                    Finish[i] = True
                    safeList.append(i)
                else:
                    break

    #如果所有进程的finish[i] = true 都满足,则表示系统处于安全状态;否则,系统处于不安全状态。
    if False in Finish:
        system_security = "不安全状态"
        print("*"*45)
        print("您输入的请求资源数:{}".format(Request))
        print("您输入的请求进程是{}".format(Request_name))
        print("系统安全性:不安全状态")
        print("*"*45)
    else:
        system_security = "系统安全"
        print("*"*45)
        print("您输入的请求进程是{}".format(Request_name))
        print("您输入的请求资源数:{}".format(Request))
        print("系统安全性:系统安全")
        print("安全序列为:",safeList)
        print("*"*45)

#银行家算法的流程
def BankerAlgorithm():
    global Allocation,Available,Max,Need,safeList,Request,Request_name, system_security
    if (Request<=Need[Request_name]).all():
        if (Request<=Available).all():                  #vector.all()表示矩阵每一项都相等
            Available -=Request
            Need[Request_name] -= Request
            Allocation[Request_name] +=Request
            safeAlgorithm()
        else:
            system_security = "请求超出可利用的资源,请等待"
            print("请求超出可利用的资源,请等待")
    else:
        system_security = "所需要的资源已超过它所宣布的最大值"
        print("所需要的资源已超过它所宣布的最大值")

#初始化各数据结构

#可利用各资源总数
Available = np.array([3,3,2])
length_Avalable = len(Available)
#各进程最大需求资源数
Max = np.array([[7,5,3],[3,2,2],[9,0,2],[2,2,2],[4,3,3]])
length_progress = len(Max)
print(length_Avalable)
#已分配各进程的资源数
Allocation = np.array([[0,1,0],[2,0,0],[3,0,2],[2,1,1],[0,0,2]])
#各进程尚需的资源数
Need = np.array([[7,4,3],[1,2,2],[6,0,0],[0,1,1],[4,3,1]])
#安全进程执行序列
safeList=[]
#各进程对各资源的请求
Request=[]
#进程名称
Request_name=""
system_security = ""


class banker(QWidget):
    '''
    ·用户界面
    '''

    def __init__(self):
        super().__init__()
        self.initUI()
        self.setIcon()

    def setIcon(self):
        palette1 = QPalette()

        palette1.setBrush(self.backgroundRole(), QBrush(QPixmap("icon/androidBackground.jpg")))   # 设置背景图片
        self.setPalette(palette1)

        self.setWindowIcon(QIcon("icon/iconbook.png"))

    def initUI(self):

        #左边的一列
        self.identifier_label = QLabel('您输入的请求进程是: [0,1,2,3,4]      ')
        self.request_label = QLabel('您输入的请求资源数量是:')
        self.security_label = QLabel('系统安全性是:')
        self.sequece_label = QLabel('安全序列是:')

        #设置开始的按钮
        self.check_btn = QPushButton('check', self)
        self.check_btn.clicked.connect(self.function)

        #右边的一列
        self.identifier_lineEdit = QLineEdit(self)
        self.security_lineEdit = QLineEdit(self)
        self.sequece_lineEdit = QLineEdit(self)
        self.request_lineEdit_1 = QLineEdit(self)
        self.request_lineEdit_2 = QLineEdit(self)
        self.request_lineEdit_3 = QLineEdit(self)

        #请求数输入的参数
        self.sub_layout  = QHBoxLayout()
        self.sub_layout.addWidget(self.request_lineEdit_1)
        self.sub_layout.addWidget(self.request_lineEdit_2)
        self.sub_layout.addWidget(self.request_lineEdit_3)

        self.main_layout = QGridLayout()
        self.main_layout.addWidget(self.identifier_label,0,0)
        self.main_layout.addWidget(self.identifier_lineEdit,0,1)
        self.main_layout.addWidget(self.request_label, 1, 0)
        self.main_layout.addItem (self.sub_layout,1,1)
        self.main_layout.addWidget(self.security_label, 2, 0)
        self.main_layout.addWidget(self.security_lineEdit, 2, 1)
        self.main_layout.addWidget(self.sequece_label, 3, 0)
        self.main_layout.addWidget(self.sequece_lineEdit, 3, 1)
        self.main_layout.addWidget(self.check_btn, 4,1)

        self.setLayout(self.main_layout)
        '''
        self.identifier_lineEdit = QLineEdit(self)
        #self.numberOfProcess.move(130, 22)

        self.sub_layout = QHBoxLayout()
        self.sub_layout.addWidget(self.check_btn)
        self.sub_layout.addWidget(self.identifier_lineEdit)

        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.identifier_label)
        self.main_layout.addLayout(self.sub_layout)
        '''
        self.setGeometry(300, 300, 600, 400)
        self.setWindowTitle('Input dialog')
        self.show()


    def function(self):
        global Request_name, Request, safeList, system_security
        Request_name = [int(self.identifier_lineEdit.text())]
        Request = np.array([int(self.request_lineEdit_1.text()), int(self.request_lineEdit_2.text()), int(self.request_lineEdit_3.text())])
        BankerAlgorithm()

        self.sequece_lineEdit.setText(str(safeList))
        self.security_lineEdit.setText(system_security)

    def center(self):
        frame_geometry = self.frameGeometry()
        center_geometry = QDesktopWidget().availableGeometry().center()
        frame_geometry.moveCenter(center_geometry)
        self.move(frame_geometry.topLeft())

    def init_widgets(self):
        # Main layout
        self.main_layout = QVBoxLayout()

        # Winner Display
        self.identifier_label = QLabel('Input participants...')

        # Participant Inputs
        self.participant_layout = QVBoxLayout()
        # Head
        self.participant_head_layout = QHBoxLayout()
        self.participant_label = QLabel('Participants:')
        self.participant_add = QPushButton('Add')
        # Inputs
        self.participant_inputs = []

        # Controls
        self.control_layout = QHBoxLayout()
        self.start_button = QPushButton('Start')
        self.stop_button = QPushButton('Stop')
        self.stop_button.setEnabled(False)


if __name__ =="__main__":

    app = QApplication(sys.argv)
    ex = banker()
    sys.exit(app.exec_())




您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

代码使用 PyQt5 创建统一界面,通过选项卡切换不同实验;一定要严格遵守要求,把所有要求都实现,不要遗漏,一定要按要求,页面的布局要简约大方【要求设计一个整合系统 使得每个项目实验可以在一个整体系统中进行演示。 (可视化界面内容格式,不做硬性要求) 实验项目一:动态资源分配算法模拟--银行家算法 实验内容: 主要用于解决多种资源被多个独立执行的进程共享的安全算法。采用矩阵存储资源的数据,通过对系统资源预分配后检查系统状态,以避免死锁的产生。 学习要求: 1.资源种类与数目可在界面进行设置,在资源分配过程中可以随时增加进程及其对资源的需求。 2.可读取样例数据(要求存放在外部文件中)进行资源种类、数目与进程数的初始化。 3.在资源分配过程中可以随时进行系统安全状态检测。 4.如果能够通过系统安全状态检测,则系统对该进程进行资源分配;当进程满足所有资源分配后能够自行释放所有资源,退出资源竞争。 5.要求进行安全性检查时按指定策略顺序进行,即按每个进程当前Need数由小至大进行排序,如果Need数相同,则按序号由小至大进行排序; 6.具有一定的数据容错性。 实验检查要求: 假设有 5 个进程(P0, P1, P2, P3, P4)。 系统提供 3 种资源(A, B, C),资源总量分别为 A=10, B=5, C=7。 输入:一组代表性的数据(下图展示) Max 最大需求矩阵: P0: [7, 5, 3] P1: [3, 2, 2] P2: [9, 0, 2] P3: [2, 2, 2] P4: [4, 3, 3] Allocation 当前分配矩阵: P0: [0, 1, 0] P1: [2, 0, 0] P2: [3, 0, 2] P3: [2, 1, 1] P4: [0, 0, 2] Available: [3, 3, 2] (表示系统中可用的 3 个 A 资源,3 个 B 资源,2 个 C 资源) 输出:安全序列 安全序列会有五种情况,均正确: 1、P3 -> P1 -> P4 -> P2 -> P0 2、P3 -> P1 -> P4 -> P0 -> P2 3、P3 -> P1 -> P0 -> P2 -> P4 4、P1 -> P3 -> P4 -> P2 -> P0 5、P1 -> P3 -> P0 -> P2 -> P4 下面请同学们尝试将可用资源能否有安全序列 比如:Available: [3, 1, 2] ->没有安全序列,发生死锁 实验项目二:通用处理机调度演示程序 实验内容:设计一个模拟处理机调度算法,以巩固和加深处理机调度的概念。 实验要求: 1. 进程调度算法包括:时间片轮转算法、先来先服务算法、短作业优先算法、静态优先权优先调度算法、高响应比调度算法 。 2. 每一个进程有一个PCB,其内容可以根据具体情况设定。 3. 进程数、进入内存时间、要求服务时间、作业大小、优先级等均可以在界面上设定。 4. 可读取样例数据(要求存放在外部文件中)进行进程数、进入内存时间、时间片长度、作业大小、进程优先级的初始化 5. 可以在运行中显示各进程的状态:就绪、执行(由于不要求设置互斥资源与进程间的同步关系,故只有两种状态) 6. 采用可视化界面,可在进程调度过程中随时暂停调度,查看当前进程的状态及相应的阻塞队列。 7. 有性能比较功能,可比较同一组数据在不同调度算法下的平均周转时间。 实验检查要求: 输入:n个进程的基本信息:进程号、到达时间、服务时长(作业大小)、优先级别;(建议进程信息从文件读取) 输出:显示调度过程, 进程数:4 时间片长度:2(仅适用于时间片轮转算法) 初始的进程列表及其属性: (从本文中读入,效果如下) 示范样例: P1:到达时间 0,运行时间 5,优先级 3 P2:到达时间 1,运行时间 3,优先级 2 P3:到达时间 2,运行时间 8,优先级 1 P4:到达时间 3,运行时间 6,优先级 4 操作:选择任意算法(时间片轮转算法、先来先服务算法、短作业优先算法、静态优先权优先调度算法、高响应比调度算法) 部分算法的结果输出: 1. 先来先服务(FCFS): 执行顺序:P1 -> P2 -> P3 -> P4 完成时间:P1 = 5, P2 = 8, P3 = 16, P4 = 22 周转时间:P1 = 5, P2 = 7, P3 = 14, P4 = 19 等待时间:P1 = 0, P2 = 4, P3 = 6, P4 = 13 平均周转时间:11.25 平均等待时间:5.75 2. 最短作业优先(SJF): 执行顺序:P1 -> P2 -> P4 -> P3 完成时间:P1 = 5, P2 = 8, P4 = 14, P3 = 22 周转时间:P1 = 5, P2 = 7, P4 = 11, P3 = 20 等待时间:P1 = 0, P2 = 4, P4 = 5, P3 = 12 平均周转时间:10.75 平均等待时间:5.25 3. 静态优先权优先调度: 执行顺序:P1 → P3 → P2 → P4 完成时间:P1 = 5, P3 = 13, P2 = 16, P4 = 22 周转时间:P1 = 5, P3 = 11, P2 = 15, P4 = 17 等待时间:P1 = 0, P3 = 3, P2 = 12, P4 = 13 平均周转时间:12.5 平均等待时间:7 4. 时间片轮转(RR, 时间片 = 2): 执行顺序: 时间段 进程 0 - 2 P1 2 - 4 P2 4 - 6 P3 6 - 8 P1 8 -10 P4 10-11 P2 11-13 P3 13-14 P1 14-16 P4 16-18 P3 18-20 P4 20-22 P3 完成时间:P1 =14, P2 = 11, P3 = 22, P4 = 20 周转时间:P1 = 14, P2 = 0, P3 = 22, P4 = 17 等待时间:P1 = 9, P2 = 7, P3 = 12, P4 = 11 平均周转时间:15.25 平均等待时间:9.75 5.高响应比调度算法(HRRN) 执行顺序:P1 → P2 → P4 → P3 完成时间:P1 = 5, P3 =8, P2 = 14, P4 = 22 周转时间:P1 = 5, P3 = 7, P2 = 11, P4 =20 等待时间:P1 = 0, P3 = 4, P2 = 5, P4 = 12 平均周转时间 = (5 + 7 + 11 + 20) / 4 = 10.75 平均等待时间 = (0 + 4 + 5 + 12) / 4 = 5.25 实验项目三:进程间通信 实验内容:在Windows环境下,1个读者和N个写者随机读写一个共享缓冲区的问题。缓冲区非满可以连续写(满时等待),缓冲区非空可以连续读(空时等待);读和写的顺利随机交替,按照写入到缓冲区的先后顺序读出的缓冲区的每一个数据,数据读出后该缓冲区即为空闲等待新数据写入;显示读者和写者的数据写入和读取的过程。编程实现基于共享内存的进程间通信问题。 实验要求: (1)当两个进程通信时需满足进程同步机制。 (2)当多个进程(大于2,约定只有一个读者和多个写者)通信时需使用信号量机制实现互斥操作。 (3)编程语言不限。 实验检查要求: 输入:参数设置1个读者,n个写者,缓冲区大小可以设置。 操作:执行读/写过程 输出: 显示读者和写者交互过程,由读者按照写入到缓冲区先后顺序读出每一个数据。 示范样例(尝试实现可视化): 输入: 读者数:1 写者数:3 缓冲区大小:3 (一般设为2的倍数,16) 输出: 时间 0.0s: 缓冲区状态: [ ][ ][ ] 写者1 写入了数据 'A'。 缓冲区状态: [A][ ][ ] 时间 0.1s: 写者2 写入了数据 'B'。 缓冲区状态: [A][B][ ] 时间 0.2s: 写者3 写入了数据 'C'。 缓冲区状态: [A][B][C] 时间 0.3s: 缓冲区已满,写者1、写者2、写者3 正在等待。 时间 0.4s: 读者读取了数据 'A'。 缓冲区状态: [ ][B][C]   实验项目四:存储管理动态分配算法模拟 实验内容:设计主界面以灵活选择某算法,且以下算法都要实现:首次适应算法、循环首次适应算法、最佳适应算法实验要求: 用一种结构化高级语言构造分区描述器,编制动态分区分配算法和回收算法模拟程序,并掌握分配算法的特点,提高编程技巧和对算法的理解和掌握。 实验检查要求: 输入:通过参数初始存储区域的大小(10000KB)。 操作:(1)可以通过界面或者命令行对整个存储空间进行分区,模拟硬盘分析A、B、C,也可以删除和合并分区; (2)根据“首次适应算法、循环首次适应算法、最佳适应算法”,选择“A、B、C”某一个分区,进行存储空间的分配。实例:分配4个作业,大小分别是50KB,100KB,150KB,200KB;然后释放作业4(200KB),释放作业1(50KB)和作业2(100KB),同一分区的连续空闲空间要自动合并。 输出: 显示读者和写者交互过程,由读者按照写入到缓冲区先后顺序读出每一个数据。 初始存储空间大小:10000KB +-----------+-----------+-----------+ | 分区 A | 分区 B | 分区 C | | 4000 KB | 3000 KB | 3000 KB | +-----------+-----------+-----------+ 1. 第一次分配:分配4个作业,大小分别为 50、100、150、200。 内存状态: [作业1 50KB][作业2 100KB][作业3 150KB][作业4 200KB][空闲3500KB] 空闲块表示意图: +------------+--------------+-----------+ | 空闲块编号 | 起始地址 (KB)| 大小 (KB) | +------------+--------------+-----------+ | 1 | 500 | 3500 | +------------+--------------+-----------+ 2. 操作:释放作业4 内存状态: [作业1 50KB][作业2 100KB][作业3 150KB][空闲3700KB] 空闲块表示意图: +------------+--------------+-----------+ | 空闲块编号 | 起始地址 (KB) | 大小 (KB) | +------------+--------------+-----------+ | 1 | 300 | 3700 | +------------+--------------+-----------+ 3. 操作:释放作业1和作业2 内存状态: [作业1 50KB][作业2 100KB][作业3 150KB][空闲200KB][空闲3500KB] 空闲块表示意图: +------------+--------------+-----------+ | 空闲块编号 | 起始地址 (KB) | 大小 (KB)| +------------+--------------+-----------+ | 1 | 300 | 3700 | | 2 | 0 | 150 | +------------+--------------+-----------+ 最终内存状态(A区): +------------+-------------+---------------+ | 空闲150KB | 作业3 150KB | 空闲3700KB | +------------+-------------+---------------+ | 地址 0-149 | 地址150-299 | 地址300-3999 | +------------+-------------+---------------+   实验项目五:存储管理之虚拟存储器模拟--页面置换算法 实验内容:编程序实现先进先出算法(FIFO)、最近最久未使用算法(LRU)算法、最佳置换算法(OPT)的具体实现过程,并计算访问命中率。 实验要求: 1.设计主界面以灵活选择某算法,且以上算法都要实现。 2. 用随机数方法产生页面走向。 3. 假定初始时页面都不在内存。 实验检查要求: 页面引用序列: 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 物理内存框数为 3 结果对比: 算法 缺页次数 总请求次数 缺页率 命中率 FIFO 15 20 75 25 LRU 12 20 60 40 OPT 9 20 45 55   实验项目六:文件系统设计 实验内容:以内存作为存储区,模拟UNIX的文件系统结构,设计一个简单的文件系统,并提供以下的文件和目录操作接口:创建文件、删除文件、打开文件、关闭文件、读文件、写文件。 实验要求: 设计文件系统的数据结构和数据结构间的关系,设计文件的基本操作算法,完成系统的总控模块编程和各个操作模块编程。上机测试各个模块,没执行一个操作,打印有关数据结构的内容,判断操作的正确性。 实验检查要求: 假设我们需要在 D1 目录下创建一个子目录 D2,然后在 D2 目录下创建一个文件 D1,并防止同名文件或目录的创建。 1. 创建目录 D1: 当前结构: / ├── D1 2. 进入 D1,创建目录 D2: 当前结构: / ├── D1 └── D2 3. 进入 D2,创建文件 D1: 当前结构: / ├── D1 └── D2 └── D1 (文件) 4. 尝试在 D2 下再次创建 D1 文件(同名文件): 错误:在目录 D2 下已存在名为 D1 的文件或目录 5. 尝试在D1 文件内写入内容:“ABCD” 6. 读取D1 文件内容   实验项目七:磁盘调度管理 实验内容:设计一个磁盘调度系统,针对磁盘访问序列,可以选择先来先服务算法(FCFS)、最短寻道时间优先算法(SSTF)、扫描算法(SCAN)、循环扫描算法(CSCAN)来实现。 实验要求: 1.系统主界面可以灵活选择某种算法。 2.每种调度算法实现之后,要计算出每种算法的平均寻道长度,并比较结果。 3.采用改进算法之后是否会使性能提高? 实验检查要求: 输入: 磁盘访问序列: 例如,给定磁盘请求序列 [98, 183, 37, 122, 14, 124, 65, 67]。 初始磁头位置: 例如,初始磁头位置为 53。 磁盘范围: 例如,磁盘磁道的范围为 0-199。 输出结果对比: 最短寻道时间优先算法(SSTF)最优   实验项目八:多进程同步模拟--桔子苹果问题 实验内容:有两类生产者,一类负责生产桔子,一类负责生产苹果;有两类消费者,一类负责消费桔子,一类负责消费苹果;他们共享一个有20个存储单元的有界缓冲区,每个存储单元只能放入一种产品(桔子/苹果)。 实验要求: 1.二类生产者与二类消费者数目均为20,即20个生产者负责生产桔子,20个生产者负责生产苹果;20个消费者负责消费桔子,20个消费者负责消费苹果 。 2.二类生产者的生产速度与二类消费者的消费速度均可独立在程序界面调节,在运行中,该值调整后立即生效。 3.多个生产者或多个消费者之间必须有共享对缓冲区进行操作的函数代码,同时需要考虑算法的效率性。 4.每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前生产者与消费者的指针位置,以及生产者和消费者线程标识符。 5.采用可视化界面,可在运行过程中随时暂停,查看当前生产者、消费者以及有界缓冲区的状态。 输入: 生产者数:20 消费者数:20 缓冲区大小:20 初始缓冲区状态:空 示范样例 生产者生产桔子和苹果的速率(同学们可以自行调节): 桔子生产者:生产桔子,每秒 2 个。 苹果生产者:生产苹果,每秒 1 个。 样例消费者消费的速率: 桔子消费者:消费桔子,每 1 秒消费 1 个。 苹果消费者:消费苹果,每 1 秒消费 1 个。 输出: 动态展示每个生产者和消费者的操作,缓冲区的实时状态,并输出程序结束时的缓冲区内容和操作日志。(如下图,此时缓冲区中桔子比苹果要多,类似这种效果即可) 缓冲区状态 桔子 桔子 桔子 空 空 空 空 空 空 空 苹果 苹果 空 空 空 空 空 空 空 空 】
05-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值