docs: 报告

This commit is contained in:
2026-04-19 19:29:25 +08:00
parent b53a15c86a
commit 075f0eda3e
5 changed files with 299 additions and 0 deletions
BIN
View File
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
%%[ ProductName: Distiller ]%%
AptosDisplay not found, using Courier.
%%[ Error: invalidfont; OffendingCommand: show ]%%
Stack:
()
%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%
%%[ Warning: PostScript error. No PDF file produced. ] %%
+289
View File
@@ -0,0 +1,289 @@
# 操作系统课程设计:进程调度模拟器实验报告
## 1. 设计目的及意义
进程调度是操作系统核心功能,负责从就绪队列中选择进程分配CPU资源。本课程设计通过实现交互式进程调度模拟器,深入理解进程调度原理,掌握基于优先级的时间片轮转和多级反馈队列轮转算法,通过可视化展示直观比较不同算法的优劣。
## 2. 系统设计
### 2.1 系统架构
```mermaid
graph TB
A[浏览器前端] -->|HTTP/JSON| B[Go HTTP服务器]
A --> A1[参数设置]
A --> A2[PRR展示]
A --> A3[MLFQ展示]
A --> A4[算法对比]
B --> B1[调度模拟API]
B --> B2[静态文件服务]
B1 --> B3[优先级时间片轮转]
B1 --> B4[多级反馈队列轮转]
```
### 2.2 核心数据结构
```go
type PCB struct {
Name, Priority, ArrivalTime, NeedTime int/string
UsedTime, State, StartTime, FinishTime int/string
QueueLevel, WaitUntil, SliceUsedTime int
}
type Snapshot struct {
Time int
Processes []PCB
Running string
Queues [][]string
Event string
}
```
### 2.3 优先级时间片轮转算法流程
```mermaid
stateDiagram-v2
[*] --> Ready: 新进程到达
Ready --> Execute: 调度器选中
Ready --> Execute: 高优先级抢占
Execute --> Ready: 时间片用完\n优先级+3
Execute --> Wait: 每3单位时间需I/O\n等待2单位时间
Execute --> Finish: 已用时间=需要时间
Wait --> Ready: 等待时间到达
Finish --> [*]
note right of Execute
优先级: 数值越小越高
支持抢占:
就绪队列有高优先级进程时
立即抢占当前进程
end note
```
### 2.4 多级反馈队列算法流程
```mermaid
stateDiagram-v2
[*] --> ReadyQ0: 新进程到达
ReadyQ0 --> ExecuteQ0: 从Q0选中(片=1)
ReadyQ1 --> ExecuteQ1: 从Q1选中(片=2)
ReadyQ2 --> ExecuteQ2: 从Q2选中(片=4)
ExecuteQ0 --> ReadyQ1: Q0片用完\n降级到Q1
ExecuteQ1 --> ReadyQ2: Q1片用完\n降级到Q2
ExecuteQ2 --> ReadyQ2: Q2片用完\n留在Q2
ExecuteQ0 --> Wait: 需要I/O
ExecuteQ1 --> Wait: 需要I/O
ExecuteQ2 --> Wait: 需要I/O
Wait --> ReadyQ0: 唤醒\n回到原队列
ExecuteQ0 --> Finish: 完成
ExecuteQ1 --> Finish: 完成
ExecuteQ2 --> Finish: 完成
Finish --> [*]
note right of ReadyQ0
三级反馈队列:
Q0: 时间片=1 (短进程优先)
Q1: 时间片=2 (中等进程)
Q2: 时间片=4 (长进程)
新进程和唤醒进程从Q0开始
end note
```
## 3. 系统实现
### 3.1 优先级时间片轮转核心代码
```go
func SimulatePriorityRR(processes []*PCB, timeSlice int) SimResult {
var readyQueue []*PCB
time := 0
for time <= maxTime {
// 唤醒等待进程,处理新到达进程
for _, p := range procs {
if p.State == StateWait && p.WaitUntil <= time {
p.State = StateReady; readyQueue = append(readyQueue, p)
}
}
// 抢占检查:高优先级进程抢占当前进程
if running != nil {
for _, p := range readyQueue {
if p.Priority < running.Priority {
running.State = StateReady
readyQueue = append(readyQueue, running); running = nil
}
}
}
// 按优先级选择进程执行
if running == nil && len(readyQueue) > 0 {
sort.Slice(readyQueue, ...) // 优先级排序
running = readyQueue[0]; readyQueue = readyQueue[1:]
}
// 执行进程,记录快照
running.UsedTime++; running.SliceUsedTime++
if running.UsedTime >= running.NeedTime {
running.State = StateFinish // 进程完成
} else if running.SliceUsedTime >= timeSlice {
running.Priority += 3 // 优先级降低
if running.UsedTime%3 == 0 {
running.State = StateWait; running.WaitUntil = time + 2 // I/O等待
}
}
time++
}
}
```
### 3.2 多级反馈队列核心代码
```go
func SimulateMLFQ(processes []*PCB, queueTimeSlices [3]int) SimResult {
queues := [3][]*PCB{} // Q0:片=1, Q1:片=2, Q2:片=4
time := 0
for time <= maxTime {
// 唤醒等待进程,新进程从Q0开始
for _, p := range procs {
if p.State == StateWait && p.WaitUntil <= time {
p.State = StateReady; queues[p.QueueLevel] = append(..., p)
}
if p.ArrivalTime == time && p.State == StateReady {
p.QueueLevel = 0; queues[0] = append(queues[0], p)
}
}
// 从最高优先级非空队列选择进程
running = selectFromMLFQ(queues)
if running.StartTime == -1 { running.StartTime = time }
// 执行进程,记录快照
running.UsedTime++; running.SliceUsedTime++
if running.UsedTime >= running.NeedTime {
running.State = StateFinish // 进程完成
} else if running.SliceUsedTime >= queueTimeSlices[running.QueueLevel] {
if running.QueueLevel < 2 {
running.QueueLevel++ // 降级到下一级队列
}
running.State = StateReady; running.SliceUsedTime = 0
}
time++
}
}
```
### 3.3 前端模拟请求
```javascript
async function doSim(algo, ts, procs) {
const resp = await fetch('/api/simulate', {
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({algorithm:algo, timeSlice:ts, processes:procs})
});
return resp.json();
}
```
### 3.4 调度过程渲染
```javascript
function renderStep(key) {
const snap = state[key].data.snapshots[state[key].step];
// 更新当前执行进程、就绪队列、状态表
if (snap.running) {
const rp = snap.processes.find(p=>p.name===snap.running);
document.getElementById('running-'+key).innerHTML =
`${rp.name} 优先级=${rp.priority} 已用=${rp.usedTime}`;
}
updateGantt(key, state[key].step); // 更新甘特图
}
```
## 4. 系统运行效果
### 4.1 调度流程对比
**示例进程配置**:P0(优先级3/到达0/需5), P1(优先级8/到达1/需3), P2(优先级5/到达2/需6), 时间片=2
**优先级时间片轮转调度序列**:
```
时间 当前执行 就绪队列 事件
t=0 P0(3) - P0开始
t=2 P2(5) P0(6) P0时间片用完,被P2抢占
t=4 P0(6) P2(8) P2时间片用完,P0继续
t=6 P1(8) P0(9),P2(11) P0再次时间片用完,P1执行
...
```
**多级反馈队列调度序列**:
```
时间 当前执行 队列状态(Q0/Q1/Q2) 事件
t=0 P0 [P0]/[]/[] P0从Q0开始
t=1 P0(Q1) []/[P0]/[] P0用完Q0片,降级到Q1
t=3 P2(Q0) [P2]/[P0]/[] P2新进程从Q0开始
t=5 P0(Q2) []/[P2]/[P0] P0降级到Q2
...
```
### 4.2 可视化展示
系统提供四个主要展示界面:
- **参数设置**:配置算法类型、时间片大小、进程参数
- **PRR展示**:动态展示优先级时间片轮转调度过程,包括就绪队列、状态表、甘特图
- **MLFQ展示**:动态展示三级队列调度过程,突出队列级别变化
- **算法对比**:比较两种算法的平均周转时间和性能特点
### 4.3 典型调度时序
```mermaid
sequenceDiagram
participant CPU
participant P0
participant P1
participant P2
Note over CPU: 优先级时间片轮转
CPU->>P0: 执行(t=0-2)
CPU->>P2: 抢占执行(t=2-4)
CPU->>P0: 继续执行(t=4-5,完成)
CPU->>P2: 继续执行(t=5-6)
CPU->>P1: 执行(t=6-8,完成)
CPU->>P2: 继续执行(t=8-9,完成)
```
## 5. 设计总结
### 5.1 关键问题解决
**抢占逻辑**:在时间循环中检查就绪队列,高优先级进程立即抢占当前进程,确保优先级高的进程及时执行。
**I/O等待机制**:PCB增加WaitUntil字段,进程每执行3单位时间后等待I/O 2单位时间,循环中检查唤醒条件。
**死锁检测**:就绪队列为空且所有进程在等待状态且无进程会唤醒时判定死锁。
### 5.2 算法特点对比
| 特点 | 优先级时间片轮转 | 多级反馈队列轮转 |
|------|----------------|----------------|
| 队列管理 | 单一就绪队列 | 三级反馈队列 |
| 时间片 | 固定统一 | 按队列递增(1,2,4) |
| 优先级调整 | 时间片后+3 | 基于队列级别动态变化 |
| 短进程响应 | 较慢 | 快速(Q0短片) |
| 长进程公平性 | 可能饥饿 | Q2长片保证 |
| 实现复杂度 | 较低 | 较高 |
### 5.3 经验体会
通过本次课程设计,深入理解了进程调度的理论与实践结合。多级反馈队列算法的"反馈"机制体现在进程的CPU使用行为会动态调整其队列位置和时间片长度。可视化展示使抽象算法原理变得直观,体现了可视化工具在教学中的价值。
### 5.4 改进方向
- 支持更多调度算法(最短作业优先、优先级抢占式等)
- 增加资源管理模拟(内存分配、设备管理)
- 优化大量进程时的渲染性能
- 添加预设测试用例库和统计分析功能
BIN
View File
Binary file not shown.
Binary file not shown.