🎯 项目概述
本项目是一个面向操作系统课程设计 的综合实验平台,采用 C 语言(算法核心)+ Python Flask(后端服务)+ 纯前端 HTML/CSS/JS(可视化界面) 三层架构,完整实现了课程设计任务书中要求的六大经典操作系统算法,并提供动态、交互式的可视化展示。
核心亮点:
- ✅ 六大算法全覆盖:HPF/FCFS调度、银行家算法、动态分区内存分配、页面置换、生产者-消费者同步
- ✅ 三层架构解耦:算法、服务、界面分离,便于理解与扩展
- ✅ 双引擎执行:优先调用高性能 C 可执行程序,缺失时自动回退 Python 实现
- ✅ 可视化大屏:深色科技风界面,支持甘特图、内存分区图、安全序列、命中率对比等动态展示
- ✅ 严格对齐课程设计:默认输入即任务书基准测试数据,输出结果与标准答案一致
📑 目录
- [🎯 项目概述](#🎯 项目概述)
- [🏗️ 项目整体架构](#🏗️ 项目整体架构)
- [📊 六大算法运行效果展示](#📊 六大算法运行效果展示)
- [1. HPF 动态高优先权调度](#1. HPF 动态高优先权调度)
- [2. FCFS 先来先服务调度](#2. FCFS 先来先服务调度)
- [3. 银行家算法(死锁避免)](#3. 银行家算法(死锁避免))
- [4. 动态分区内存分配](#4. 动态分区内存分配)
- [5. 页面置换算法](#5. 页面置换算法)
- [6. 生产者-消费者同步](#6. 生产者-消费者同步)
- [📚 课程设计任务书基准测试数据](#📚 课程设计任务书基准测试数据)
- [2.1 HPF 动态高优先权调度(实验一)](#2.1 HPF 动态高优先权调度(实验一))
- [2.2 银行家算法(实验二)](#2.2 银行家算法(实验二))
- [2.3 动态分区内存分配(实验三)](#2.3 动态分区内存分配(实验三))
- [2.4 页面置换算法(实验四)](#2.4 页面置换算法(实验四))
- [2.5 生产者-消费者同步(实验五)](#2.5 生产者-消费者同步(实验五))
- [🚀 快速开始](#🚀 快速开始)
- 环境要求
- 一键运行(Windows)
- [编译 C 算法核心(可选)](#编译 C 算法核心(可选))
- [📁 项目结构](#📁 项目结构)
- [🔍 常见问题 FAQ](#🔍 常见问题 FAQ)
- [📈 性能基准](#📈 性能基准)
- [🎉 总结](#🎉 总结)
🏗️ 项目整体架构
技术栈与通信流程
前端大屏 (index.html + CSS + JS)
│
▼ HTTP fetch (JSON)
│
app.py (Flask) ------ 中枢调度层
│
├── subprocess.run() ------→ C 可执行文件 (*.exe)
│ │
│ ▼ 读写 JSON 文件
│ │
│ data/ (输入) & output/ (输出)
│
└── Python import (回退) ------→ Python 调度器 (*_scheduler.py)
│
▼ 读写 JSON 文件
│
data/ (输入) & output/ (输出)
关键设计说明:
- C 程序完全独立 :源码中不包含
Python.h等 Python C API 调用,通过 JSON 文件和子进程 (subprocess) 与 Python 层通信。 - 优雅降级:若 C 可执行文件不存在,Flask 自动调用等价的 Python 实现,保证功能可用。
- 纯前端界面:通过 HTTP fetch 调用 Flask API 获取 JSON 数据,实现算法结果的可视化渲染。
📊 六大算法运行效果展示

1. HPF 动态高优先权调度

- 规则:优先数越大优先级越高;进程运行 1 时间片后优先数 -1,放回就绪队列。
- 输出:完整调度过程、PCB 状态表、甘特图。
2. FCFS 先来先服务调度

- 规则:按到达时间依次调度,相同到达时间保持输入顺序。
- 输出:进程调度顺序、完成时间、周转时间等。
3. 银行家算法(死锁避免)

- 基准数据:5 进程、4 类资源。
- 功能:输出安全序列、试探分配结果、资源分配图。
4. 动态分区内存分配

- 总容量:512KB。
- 策略:首次适应 (First Fit)、最佳适应 (Best Fit)、最坏适应 (Worst Fit) 三种策略并行对比。
- 可视化:空闲分区表动态变化图。
5. 页面置换算法

- 引用串:2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2(共12次访问)。
- 算法:FIFO、LRU、OPT 三种算法并行对比。
- 输出:命中次数、缺页率、每步页框状态表。
6. 生产者-消费者同步

- 同步机制:POSIX 风格信号量 (empty/full/mutex)。
- 可视化:缓冲区状态、生产者/消费者活动序列。
提示:点击任意图片可查看原图大图。
📚 课程设计任务书基准测试数据
2.1 HPF 动态高优先权调度(实验一)
输入:3 个进程(a, b, c),优先数/总运行时间分别为 a(2,2)、b(1,1)、c(3,2)。
标准推演结果:
| 轮次 | 运行进程 | 全部 PCB(优先数/已运行) | 就绪队列 |
|---|---|---|---|
| 1 | c | a(2,0)、b(1,0)、c(3,0) | c(3), a(2), b(1) |
| 2 | a | a(2,0)、b(1,0)、c(2,1) | a(2), c(2), b(1) |
| 3 | c | a(1,1)、b(1,0)、c(2,1) | c(2), a(1), b(1) |
| 4 | a | a(1,1)、b(1,0)、c(完成) | a(1), b(1) |
| 5 | b | a(完成)、b(1,0)、c(完成) | b(1) |
调度顺序:c → a → c → a → b
2.2 银行家算法(实验二)
基础数据:5 进程(P0-P4),4 类资源(A/B/C/D)。
| 进程 | Allocation | Max | Need=Max-Allocation |
|---|---|---|---|
| P0 | (0,0,1,2) | (0,0,4,4) | (0,0,3,2) |
| P1 | (1,0,0,0) | (2,7,5,0) | (1,7,5,0) |
| P2 | (1,3,5,4) | (3,6,10,10) | (2,3,5,6) |
| P3 | (0,3,3,2) | (0,9,8,4) | (0,6,5,2) |
| P4 | (0,0,1,4) | (0,6,6,10) | (0,6,5,6) |
Available = (1,6,2,2)
T0 初始安全序列:P0 → P3 → P1 → P2 → P4(按 P0~P4 升序扫描)
P2 Request=(1,2,2,2) :Request ≤ Need ✅;Request ≤ Available ✅;试探分配后系统进入不安全态 → 驳回
2.3 动态分区内存分配(实验三)
配置 :512KB,起始地址 0。
请求序列:申请300K → 申请100K → 释放300K → 150K → 30K → 40K → 60K → 释放30K → 再次申请100K。
- First Fit:最后 100K 可成功分配(尾端剩余 112K 空闲块)。
- Best Fit:最后 100K 无法分配(最大空闲块仅 90K,外部碎片)。
2.4 页面置换算法(实验四)
标准引用串:2, 3, 2, 1, 5, 2, 4, 5, 3, 2, 5, 2(共12次访问),物理页框 F=3。
| 算法 | 缺页次数 | 缺页率 |
|---|---|---|
| FIFO | 8 | 66.7% |
| LRU | 7 | 58.3% |
| OPT | 6 | 50.0% |
2.5 生产者-消费者同步(实验五)
信号量初始化 :empty = N, full = 0, mutex = 1。
标准流程:
- 生产者:P(empty) → P(mutex) → 生产 → V(mutex) → V(full)
- 消费者:P(full) → P(mutex) → 消费 → V(mutex) → V(empty)
🚀 快速开始
环境要求
| 组件 | 最低要求 | 备注 |
|---|---|---|
| Python | 3.8+ | 3.12 测试通过 |
| Flask | 2.0+ | pip install flask |
| 浏览器 | Chrome/Edge/Firefox | 支持 CSS3 / ES6 |
| MinGW(可选) | gcc | 用于编译 C 程序(非必需) |
一键运行(Windows)
- 下载项目代码。
- 双击
run.bat文件启动 Flask 服务。 - 浏览器打开
http://127.0.0.1:5000。
编译 C 算法核心(可选)
bash
gcc -O2 -Wall -o backend\hpf_scheduler.exe backend\hpf_scheduler.c
gcc -O2 -Wall -o backend\fcfs_scheduler.exe backend\fcfs_scheduler.c
gcc -O2 -Wall -o backend\banker_scheduler.exe backend\banker_scheduler.c
gcc -O2 -Wall -o backend\memory_scheduler.exe backend\memory_scheduler.c
gcc -O2 -Wall -o backend\page_scheduler.exe backend\page_scheduler.c
gcc -O2 -Wall -o backend\pc_scheduler.exe backend\pc_scheduler.c
📁 项目结构
OS_keshe/
├── README.md # 本文档
├── backend/
│ ├── app.py # Flask 主程序
│ ├── hpf_scheduler.c/.py # HPF 调度
│ ├── fcfs_scheduler.c/.py # FCFS 调度
│ ├── banker_scheduler.c/.py # 银行家算法
│ ├── memory_scheduler.c/.py # 动态分区内存分配
│ ├── page_scheduler.c/.py # 页面置换
│ ├── pc_scheduler.c/.py # 生产者-消费者
│ ├── test_verify.py # C/Python 输出一致性验证
│ ├── test_api.py # Flask API 验证
│ ├── output/ # JSON 输出目录
│ └── data/ # JSON 输入目录
└── frontend/
├── index.html # 主界面 + 实验界面
├── css/style.css # 深色科技风样式
└── js/app.js # 视图切换/甘特图/API 调用
🔍 常见问题 FAQ
Q1: 没有安装 MinGW,能正常运行吗?
能。Flask 优先调用 C exe,若不存在则自动回退 Python 实现,输出结果一致。
Q2: 如何自定义进程/请求/引用串?
前端参数面板直接修改,或 POST JSON 到对应 API。
Q3: 为什么 Best-Fit 最后 100K 分配失败而 First-Fit 成功?
Best-Fit 倾向切出刚好大小的空闲块,留下大量外部碎片。示例中 BF 最终最大空闲块仅 90K,而 FF 保留尾部连续 112K。
Q4: LRU 与 FIFO 在本示例为什么不同?
LRU 命中时将页面"最新使用"提升,而 FIFO 命中时队列不动。进程 2 在第 3 步命中后 LRU 会将其升序,后续仍在内存中,因此 LRU 比 FIFO 少一次缺页。
Q5: 试探分配在代码中如何回滚?
在 Available、AllocationP、NeedP 三个向量做一次本地修改后调用 safe();返回 false 时按相同公式反向回滚 Available、Allocation、Need。
📈 性能基准
在 Python 3.12、20 个数据对象、1000 次迭代、-O2 编译环境下测试:
| 算法 | Python (ms/1000) | 时间复杂度 | 优化点 |
|---|---|---|---|
| HPF | ~45 | O(nT) | 按优先级有序取就绪队列首 |
| FCFS | ~23 | O(n log n) | Timsort 稳定排序 |
| 银行家算法 | ~53 | O(mn) | 更新向量后 break 内层循环 |
| 页面置换 | ~195 | O(F·n) | OPT next_use 预计算 O(n) 一次扫描代替 O(nF) 每步重查 |
| 内存分配 | ~37 | O(k·r) | 按地址有序插入 + 双邻居合并 |
| 生产者-消费者 | ~28 | O(E) | 事件按时间索引 O(1) |
C 版通常比 Python 版快 5-20 倍。
🎉 总结
本项目将操作系统课程设计中抽象的算法原理转化为直观、交互的可视化模拟系统,不仅严格对齐课程设计任务书的基准测试数据,还通过三层架构、双引擎执行、优雅降级等工程实践,展示了如何将理论算法落地为可运行、可验证、可扩展的软件系统。适合高校学生作为课程设计参考,也适合开发者学习 C/Python/前端全栈协作的项目实践。
版权声明:本文档及项目代码仅供学习交流使用,请遵守相关开源协议。