【操作系统实验】进程管理与内存分配模拟程序-含可运行有界面的Python代码

news2024/12/26 15:21:12

本文是博主之前做的操作系统实验,现在将完整代码和效果图免费放在下面,供大家参考,如果觉得有用,希望大家可以三连+关注支持!!!!!!

实验目的

设计编写OS进程与内存管理模拟程序,模拟OS进程的创建、阻塞、唤醒、撤销等进程控制以及OS内存管理方法和过程,加深操作系统进程控制原语主要任务和过程的理解,加深操作系统内存分配的基本策略,加深操作系统以进程为核心的完整架构的理解。提高综合性实验的分析、设计及编程实现能力。

实验内容

设计一个OS进程与内存管理模拟程序,要求:
程序运行后提供一个交互界面或窗口,允许用户输入以下命令并可以滴对命令进行解释执行,
creatproc:提交作业命令,要求用户提供作业估计运行时长和内存大小需求。该命令的解释执行过程为对该作业创建对应的进程,完成PCB建立、存储空间分配等工作。(既执行OS的创建进程原语)
killproc 进程号:终止进程命令。该命令的解释执行过程为对进程进行撤销,回收存储空间和PCB。
iostrartproc 进程号:阻塞进程命令。该命令的解释执行过程为对处于运行状态的进程进行阻塞操作,进程状态转为阻塞状态。
iofinishproc 进程号:唤醒进程命令。该命令的解释执行过程为对处于阻塞状态的进程进行唤醒操作,进程状态转为就绪状态。
psproc:显示所有进程状态命令。该命令的解释执行过程为显示出所有进程的状态信息,主要包括进程id,进程状态,存储空间地址。
mem:显示内存空间使用情况信息。该命令的解释执行过程为显示内存空间的占用和空闲情况。
设计思路提示:内存空间可用数组模拟,主要原语模拟实现,包括创建进程,终止进程,阻塞进程,唤醒进程,进程调度等原语。进程调度算法可选择 FCFS、RR、SJF中任意一种。内存分配可选择可变分区策略或页式内存分配方案中任意一种。
程序设计语言不限。

效果展示

运行程序

依次创建三个进程,运行时间分别为5、4、3,内存均为100

查看此时的进程状态和内存分配情况:

开始调度由于使用的是SJF调度算法,所有会先调度进程3:

每点一次调度,正在运行的进程的剩余时间减一:

下面测试内存不够的情况下,创建内存会发生什么,创建一个内存大小为800的进程如图报错

下面测试阻塞进程和唤醒进程的功能,要先阻塞进程3,然后调度,让进程2运行,然后阻塞进程2,然后调度,让进程1运行,然后阻塞:

依次唤醒三个进程:

测试终止进程功能,将进程2终止:

内存情况

然后检验内存分配的首次适应算法的功能,即创建一个进程,内存大小为101

最后一直点调度,直到进程全部结束

完整代码

from tkinter import *
import random
cnt = 0
# 定义进程类
class Process:
    def __init__(self, pid, runtime, memsize):
        self.pid = pid
        self.runtime = runtime
        self.memsize = memsize
        self.status = "Ready"
        self.memstart = -1

# 定义内存类
class Memory:
    def __init__(self, size):
        self.size = size
        self.memory = [0] * size
        self.free_blocks = [(0, size-1)]

    def allocate(self, size, pid):
        for i, block in enumerate(self.free_blocks):
            if block[1]-block[0]+1 >= size:
                start = block[0]
                end = start + size - 1
                self.free_blocks.pop(i)
                if block[1] != end:
                    self.free_blocks.insert(i, (end+1, block[1]))
                if block[0] != start:
                    self.free_blocks.insert(i, (block[0], start-1))
                for j in range(start, end+1):
                    self.memory[j] = pid
                return start
        return -1

    def free(self, start, pid):
        end = start + pid.memsize - 1
        for i in range(start, end+1):
            self.memory[i] = 0
        self.free_blocks.append((start, end))
        self.free_blocks.sort()

# 定义进程列表和内存对象
process_list = []
memory = Memory(1024)

# 创建进程命令,需要用户输入作业运行时间和内存需求
def create_proc():
    time = entry1.get()
    mem = entry2.get()
    global cnt
    cnt = cnt + 1
    pid = cnt
    runtime = int(time)
    memsize = int(mem)
    process = Process(pid, runtime, memsize)
    memstart = memory.allocate(memsize, pid)
    if memstart == -1:
        status_text.insert(END,"Memory allocation failed.\n")
        return
    process.memstart = memstart
    process_list.append(process)
    status_text.insert(END,"Process created with PID {}.\n".format(pid))


# 终止进程命令,需要用户输入要终止的进程ID
def kill_proc1():
    pid = entry1.get()
    pid = int(pid)
    for i, process in enumerate(process_list):
        if process.pid == pid:
            process.status = "Terminated"
            memory.free(process.memstart, process)
            del process_list[i]
            status_text.insert(END,"Process {} terminated.\n".format(pid))
            return
    status_text.insert(END,"Process {} not found.\n".format(pid))
    show_proc()

# 终止进程命令,自动
def kill_proc2(pid):
    for i, process in enumerate(process_list):
        if process.pid == pid:
            process.status = "Terminated"
            memory.free(process.memstart, process)
            del process_list[i]
            status_text.insert(END,"Process {} terminated.\n".format(pid))
            return
    status_text.insert(END,"Process {} not found.\n".format(pid))
    show_proc()

# 阻塞进程命令,需要用户输入要阻塞的进程ID
def block_proc():
    pid = entry1.get()
    pid = int(pid)
    for process in process_list:
        if process.pid == pid:
            if process.status == "Running":
                process.status = "Blocked"
                status_text.insert(END,"Process {} blocked.\n".format(pid))
                return
            else:
                status_text.insert(END,"Process {} not running.\n".format(pid))
                return
    status_text.insert(END,"Process {} not found.\n".format(pid))

# 唤醒进程命令,需要用户输入要唤醒的进程ID
def unblock_proc():
    pid = entry1.get()
    pid = int(pid)
    for process in process_list:
        if process.pid == pid:
            if process.status == "Blocked":
                process.status = "Ready"
                status_text.insert(END,"Process {} unblocked.\n".format(pid))
                return
            else:
                status_text.insert(END,"Process {} not blocked.\n".format(pid))
                return
    status_text.insert(END,"Process {} not found.\n".format(pid))

# 执行调度命令,根据短时间优先非抢占式算法选择下一个要运行的进程
def schedule():
    shortest_process = None
    shortest_runtime = sys.maxsize
    for process in process_list:
        if process.status == "Running":
            process.runtime -= 1
            if process.runtime  == 0:
                kill_proc2(process.pid)
                return
            if shortest_process is None or process.runtime  < shortest_runtime:
                shortest_process = process
                shortest_runtime = process.runtime
    if shortest_process is None:
        for process in process_list:
            if process.status == "Ready":
                if shortest_process is None or process.runtime < shortest_runtime:
                    shortest_process = process
                    shortest_runtime = process.runtime
        if shortest_process is not None:
            shortest_process.status = "Running"
            status_text.insert(END,"Process {} running.\n".format(shortest_process.pid))
    else:
        status_text.insert(END,"Process {} running.\n".format(shortest_process.pid))
    show_proc()

# 显示进程状态命令,将进程列表和它们的状态显示在屏幕上
def show_proc():
    # 清空进程显示区域
    proc_list.delete(0, END)

    # 遍历进程列表,将每一个进程的信息添加到进程显示区域中
    for proc in process_list:
        proc_info = f"进程号:{proc.pid},状态:{proc.status},剩余时间:{proc.runtime },内存大小:{proc.memsize},地址:{proc.memstart}"
        proc_list.insert(END, proc_info)

# 显示内存分配情况命令,将内存分配情况显示在屏幕上
# 定义内存显示函数,将数据写入内存文本框
def show_mem():
    # 清空进程显示区域
    memory_text.delete(1.0, END)
    i = 0
    while i < memory.size:
        if memory.memory[i] == 0:
            block_start = i
            block_size = 0
            while i < memory.size and memory.memory[i] == 0:
                block_size += 1
                i += 1
            memory_text.insert(END, "Free block: Start = {}, Size = {}\n".format(block_start, block_size))
        else:
            pid = memory.memory[i]
            block_start = i
            block_size = 0
            while i < memory.size and memory.memory[i] == pid:
                block_size += 1
                i += 1
            memory_text.insert(END, "Used block: PID = {}, Start = {}, Size = {}\n".format(pid, block_start, block_size))

# 创建主窗口
root = Tk()
root.title("OS进程与内存管理模拟程序")

top_frame = Frame(root)
top_frame.pack(side=TOP)

# 添加进程运行时间输入框和标签
run_time_lbl = Label(top_frame, text="进程运行时间/进程号:")
run_time_lbl.pack(side=LEFT)

entry1 = Entry(top_frame)
entry1.pack(side=LEFT)

# 添加进程内存大小输入框和标签
mem_size_lbl = Label(top_frame, text="进程内存大小:")
mem_size_lbl.pack(side=LEFT)

entry2 = Entry(top_frame)
entry2.pack(side=LEFT)

button1 = Button(top_frame, text="创建进程", command=create_proc)
button1.pack(side=LEFT)

button2 = Button(top_frame, text="终止进程", command=kill_proc1)
button2.pack(side=LEFT)

button3 = Button(top_frame, text="阻塞进程", command=block_proc)
button3.pack(side=LEFT)

button4 = Button(top_frame, text="唤醒进程", command=unblock_proc)
button4.pack(side=LEFT)

button5 = Button(top_frame, text="调度", command=schedule)
button5.pack(side=LEFT)

button6 = Button(top_frame, text="显示进程状态", command=show_proc)
button6.pack(side=LEFT)

button7 = Button(top_frame, text="显示内存分配情况", command=show_mem)
button7.pack(side=LEFT)

# 添加进程状态显示区域,并将它放在窗口的左侧
left_frame = Frame(root, width=300, height=400)
left_frame.pack(side=LEFT)

# 添加垂直和水平滚动条
y_scrollbar = Scrollbar(left_frame)
y_scrollbar.pack(side=RIGHT, fill=Y)

x_scrollbar = Scrollbar(left_frame, orient=HORIZONTAL)
x_scrollbar.pack(side=BOTTOM, fill=X)

# 添加进程列表框,并使其具有垂直和水平滚动条控制的能力
proc_list = Listbox(left_frame, yscrollcommand=y_scrollbar.set, xscrollcommand=x_scrollbar.set, width=40, height=20)
proc_list.pack(side=LEFT, fill=BOTH)

# 设置滚动条控制
y_scrollbar.config(command=proc_list.yview)
x_scrollbar.config(command=proc_list.xview)

# 将进程列表框和滚动条添加到左侧框架中

# 添加状态信息显示区域,并将其放在进程列表和内存分配情况显示之间
status_frame = Frame(root)
status_frame.pack(side=LEFT)

status_label = Label(status_frame, text="状态信息")
status_label.pack()

status_text = Text(status_frame, width=40, height=20)
status_text.pack(side=LEFT)

# 添加垂直滚动条并将其与状态文本框配对
scrollbar = Scrollbar(status_frame, orient=VERTICAL, command=status_text.yview)
scrollbar.pack(side=RIGHT, fill=Y)
status_text.configure(yscrollcommand=scrollbar.set)




# 添加内存分配情况显示区域,并将它放在窗口的右侧
right_frame = Frame(root)
right_frame.pack(side=RIGHT)

memory_label = Label(right_frame, text="内存分配情况")
memory_label.pack()

memory_text = Text(right_frame, bg="white", width=40, height=20)
memory_text.pack()

# 进入主循环
root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

15. 线性代数 - 克拉默法则

文章目录 克拉默法则矩阵运算Hi,大家好。我是茶桁。 上节课我们在最后提到了一个概念「克拉默法则」,本节课,我们就来看看到底什么是克拉默法则。 克拉默法则 之前的课程我们一直在强调,矩阵是线性方程组抽象的来的。那么既然我们抽象出来了,有没有一种比较好的办法高效…

合宙Air724UG LuatOS-Air LVGL API控件-二维码(Qrcode)

二维码&#xff08;Qrcode&#xff09; 示例代码 qrcodelvgl.qrcode_create(lvgl.scr_act(),nil)lvgl.qrcode_set_txt(qrcode,"https://doc.openluat.com/home")lvgl.obj_set_size(qrcode,400,400)lvgl.obj_align(qrcode, nil, lvgl.ALIGN_CENTER, 0, 0)创建 可以通…

496. 下一个更大元素 I

class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {// 存储numx2右侧第一个比它的元素数值std::unordered_map<int, int> index;std::stack<int> sta;for (int i nums2.size()-1; i &…

uniapp项目实践总结(十四)封装存储和路由方法

导语&#xff1a;在日常 APP 开发过程中&#xff0c;经常要用到数据的存储、获取和删除等操作以及页面导航之间的跳转&#xff0c;为此&#xff0c;封装了一个两个简单的方法来统一调用。 目录 原理分析方法实现实战演练案例展示 原理分析 主要是以下 API。 uni.setStorage…

xcode iOS 在app文件中开启访问 Document Directory

xcode iOS 在app文件中开启访问 Document Directory 在 Plist 中设置 LSSupportsOpeningDocumentsInPlace为 YES 且UIFileSharingEnabled为 YES &#xff08;这个不添加好像也可以&#xff09; 可以从系统的Files应用中访问应用的 Documents 目录 电脑 助手也可以访问 开…

视频号挂公众号链接最新教程方法,赶紧来看

玩视频号的朋友&#xff0c;尤其是靠挂公众号引流的朋友&#xff0c;肯定心里非常清楚&#xff0c;就在八月初&#xff0c;视频号放大招了&#xff0c;可以说这个大招是完全把公众号的路给堵死了&#xff0c;视频号出了什么新规呢&#xff0c;大家来看看。 第一个规则是&#…

无涯教程-JavaScript - IMTAN函数

描述 IMTAN函数以x yi或x yj文本格式返回复数的切线。复数的切线由以下公式计算- tan(z)正弦(z)/cos(z) 语法 IMTAN (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the tangent.Required Notes Excel中的复数仅存储为文本。…

最新keil安装出现的无数问题记录及解决办法

报错问题现象如下&#xff1a; *** Target Target 1 uses ARM-Compiler Default Compiler Version 5 which is not available. 安装最新keil 5 出现无数个问题。 我使用GD32去跑&#xff0c;或者STM32去跑&#xff0c;都是这个问题。 一、我先解决了GD32的问题&#xff1a;…

阻塞队列学习总结

ArrayBlockingQueue&#xff1a;一个由数组结构组成的有界阻塞队列。 LinkedBlockingQueue&#xff1a;一个由链表结构组成的有界阻塞队列。 PriorityBlockingQueue&#xff1a;一个支持优先级排序的无界阻塞队列。 DelayQueue&#xff1a;一个使用优先级队列实现的延迟无界…

分库分表实战

数据分片与分片算法 分库分表的第一性原理&#xff0c;那就是&#xff1a;存储容量和性能容量。只有对核心业务表才会精心进行分库分表的设计。 首先我们了解一下数据分片是什么意思&#xff1f; 本质上的分库分表不就是数据分片吗&#xff1f;定义就是&#xff1a;按照某个…

BBR 带宽估计的延后累加

一个关于时延统计分布的小测试&#xff0c;用 netem delay jitter distribution pareto 模拟&#xff0c;得到下面的结果&#xff1a; netem 的 jitter 并不是真 jitter&#xff0c;只是通过延时阻滞部分报文模拟 jitter&#xff0c;对保序流而言&#xff0c;就表现为乱序&am…

搭建自己的OCR服务,第一步:选择合适的开源OCR项目

一、OCR是什么&#xff1f; 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;是指对文本资料的图像文件进行分析识别处理&#xff0c;获取文字及版面信息的过程。 亦即将图像中的文字进行识别&#xff0c;并以文本的形式返回。 二、OCR的基本流程 1…

Science子刊 | 将CAR-T细胞疗法与造血干细胞移植相结合 或许 能治疗所有血液癌症...

来源&#xff1a;BRUNO DELESSARD/CHALLENGES-REA/REDUX 新的CAR-T细胞疗法有望能治疗几乎所有血液癌症。目前&#xff0c;该疗法已被批准用于五种亚型的血液癌症。宾夕法尼亚大学帕尔曼医学院的科学家们在预临床试验中展示了这种方法的潜在效能。 2023年8月31日&#xff0c;发…

动态路由的主流算法

路由器就是一台网络设备&#xff0c;它有多张网卡。当一个入口的网络包送到路由器时&#xff0c;它会根据一个本地的转发信息库&#xff0c;来决定如何正确地转发流量。这个转发信息库通常被称为路由表。 一张路由表中会有多条路由规则。每一条规则至少包含这三项信息。 目的…

vscode 调试 ROS2

1、在下列目录同层级找到.vscode文件夹 . ├── build ├── install ├── log └── src 2、 安装ros插件 3、创建tasks.json文件&#xff0c;添加下列内容 //代替命令行进行编译 {"version": "2.0.0","tasks": [{"label": &…

一窥未来:PyQt5引领下一代Python GUI开发

PyQt5 是一个用于创建图形用户界面&#xff08;GUI&#xff09;的强大工具包&#xff0c;它基于 Qt 库&#xff0c;为 Python 提供了丰富的 GUI 开发能力。无论是初学者还是有经验的开发者&#xff0c;都可以通过本文深入了解如何使用 PyQt5 来构建各种各样的界面应用程序。本文…

CUDA说明和安装[window]

文章目录 1、查看版本信息查看GPU查看cuda版本其他方法 2区分 了解cudaCUDA ToolkitNVCCcuDNN 3/ 安装过程4/版本的问题CUDA Toolkit和 显卡驱动 的版本对应CUDA / CUDA Toolkit和cuDNN的版本对应 5/关于CUDA和Cudnn**5.1 CUDA的命名规则****5.2 如何查看自己所安装的CUDA的版本…

力扣接雨水(解析)

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] …

lv4 嵌入式开发-2 Linux文件IO

1 文件的打开 1.1 标准I/O - 打开文件 下列函数可用于打开一个标准I/O流&#xff1a; FILE *fopen (const char *path, const char *mode);成功时返回流指针&#xff1b;出错时返回NULL标准I/O – fopen – mode参数 示例 #include <stdio.h> int main(int argc, ch…

微信支付-Native支付(网页二维码扫码微信支付)简单示例

目录 概述 界面展示 & 前端代码&#xff08;Vue&#xff09; 后端实现&#xff08;SpringBoot&#xff09; Maven依赖 下单接口&#xff08;主要功能代码&#xff09; 支付成功回调接口 测试&#xff08;后端线上环境&#xff09; 概述 本篇博文主要演示和说明网页扫…