feat: 增加周转时间部分的设置

This commit is contained in:
ViperEkura 2026-04-26 17:27:01 +08:00
parent 6031dc3198
commit eb1de7b3d1
11 changed files with 963 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__

165
experiment/README.md Normal file
View File

@ -0,0 +1,165 @@
# 进程调度算法实验
## 实验目的
1. 理解进程调度的基本概念和原理
2. 掌握 FCFS、SJF、RR、优先级调度、MLFQ 等算法
3. 通过模拟实验比较各算法的性能指标
## 实验环境
- Python 3.x
## 文件结构
```
experiment/
├── README.md # 实验文档
└── code/ # 代码目录
├── base.py # 基础类Process, ProcessScheduler
├── main.py # 主程序入口
├── fcfs.py # 先来先服务调度
├── sjf.py # 短作业优先调度 (含 SRTF)
├── rr.py # 时间片轮转调度
├── priority.py # 优先级调度
└── mlfq.py # 多级反馈队列调度
```
## 性能指标
设进程 $P_i$ 的到达时间为 $AT_i$,完成时间为 $CT_i$,服务时间为 $BT_i$,首次运行时间为 $ST_i$
### 周转时间 (Turnaround Time)
$$
TAT_i = CT_i - AT_i
$$
**定义**:进程从提交到完成的总时间
**含义**:衡量进程在系统中停留的总时长,包括等待时间和实际运行时间
### 带权周转时间 (Weighted Turnaround Time)
$$
WTAT_i = \frac{TAT_i}{BT_i}
$$
**定义**:周转时间与服务时间的比值
**含义**:衡量进程的相对延迟,比值越大说明等待时间相对于服务时间越长
- $WTAT_i = 1$:理想情况,无额外等待
- $WTAT_i > 1$:存在等待时间
- $WTAT_i$ 越小越好
### 等待时间 (Waiting Time)
$$
WT_i = TAT_i - BT_i = (CT_i - AT_i) - BT_i
$$
**定义**:进程在就绪队列中等待的时间总和
**含义**:不包含实际运行时间,只计算等待 CPU 的时间
### 响应时间 (Response Time)
$$
RT_i = ST_i - AT_i
$$
**定义**:从提交到首次运行的时间
**含义**:用户感受到的"启动延迟",对于交互系统尤为重要
### 性能指标总结
| 指标 | 公式 | 优化目标 | 适用场景 |
|------|------|----------|----------|
| 周转时间 | $CT - AT$ | 越小越好 | 批处理系统 |
| 带权周转时间 | $(CT-AT)/BT$ | 越小越好 | 公平性评估 |
| 等待时间 | $TAT - BT$ | 越小越好 | 调度算法比较 |
| 响应时间 | $ST - AT$ | 越小越好 | 交互系统 |
## 算法公式
### FCFS 周转时间
$$
TAT_i = \sum_{j=1}^{i} BT_j - AT_i \quad (AT_i \leq AT_{i+1})
$$
### SJF 平均等待时间最小化
$$
\min \frac{1}{n} \sum_{i=1}^{n} WT_i
$$
### RR 吞吐量
$$
\text{吞吐量} = \frac{n}{T_{\text{总}}} \quad \text{其中 } T_{\text{总}} = CT_{\text{max}} - AT_{\text{min}}
$$
## 运行方式
```bash
cd code
# 使用演示数据5个进程
python main.py --demo
# 生成随机测试数据默认5个进程种子42
python main.py
# 生成100个随机进程
python main.py -n 100
# 固定种子生成1000个进程可复现
python main.py -n 1000 -s 42
# 自定义参数范围
python main.py -n 50 --arrival 0,100 --burst 5,50 --priority 1,5
# 运行指定算法
python main.py -n 20 -a FCFS,SJF,RR
# 每次运行使用不同随机数据
python main.py -n 20 -s -1
```
### 命令行参数说明
| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-n, --num` | 进程数量 | 5 |
| `-s, --seed` | 随机种子 | 42固定 |
| `-a, --algo` | 运行的算法 | 全部 |
| `--demo` | 使用预设演示数据 | False |
| `--arrival` | 到达时间范围 | 0,50 |
| `--burst` | 服务时间范围 | 1,20 |
| `--priority` | 优先级范围 | 1,10 |
### 预设演示数据
| PID | 到达时间 | 服务时间 | 优先级 |
|-----|----------|----------|--------|
| P1 | 0 | 7 | 3 |
| P2 | 2 | 4 | 1 |
| P3 | 4 | 1 | 4 |
| P4 | 5 | 4 | 2 |
| P5 | 6 | 2 | 3 |
## 思考题
1. 分析 FCFS 和 SJF 各自的优缺点
2. 为什么说 SJF 可以获得最短的平均等待时间?
3. RR 算法中,时间片大小对系统性能有何影响?
4. 多级反馈队列如何解决"长作业饥饿"问题?
5. 如何证明某种调度算法是最优的?
## 参考资料
- 操作系统概念Abraham Silberschatz
- 现代操作系统Andrew S. Tanenbaum

173
experiment/code/base.py Normal file
View File

@ -0,0 +1,173 @@
#!/usr/bin/env python3
"""
进程调度算法模块 - 公共基础类
"""
import random
from dataclasses import dataclass, field
from typing import List, Dict, Optional
@dataclass
class Process:
"""进程数据结构"""
pid: str
arrival_time: int = 0
burst_time: int = 0
priority: int = 0 # 数值越小优先级越高
remaining_time: int = field(default=0)
start_time: int = -1
completion_time: int = 0
waiting_time: int = 0
turnaround_time: int = 0
weighted_turnaround_time: float = 0.0 # 带权周转时间 = 周转时间/服务时间
response_time: int = 0
def __post_init__(self):
self.remaining_time = self.burst_time
def reset(self):
"""重置进程状态"""
self.remaining_time = self.burst_time
self.start_time = -1
self.completion_time = 0
self.waiting_time = 0
self.turnaround_time = 0
self.weighted_turnaround_time = 0.0
self.response_time = 0
class ProcessScheduler:
"""进程调度器基类"""
def __init__(self, processes: List[Process]):
self.processes = [p for p in processes]
self.results: List[Process] = []
def calculate_metrics(self, p: Process, current_time: int):
"""
计算进程性能指标
周转时间 (Turnaround Time): CT - AT
进程从提交到完成的总时间
带权周转时间 (Weighted Turnaround Time): TAT / BT
周转时间与服务时间的比值衡量进程相对延迟
值越大说明等待时间相对服务时间越长
等待时间 (Waiting Time): TAT - BT
进程在就绪队列中等待的时间总和
响应时间 (Response Time): ST - AT
从提交到首次运行的时间
"""
p.completion_time = current_time
p.turnaround_time = p.completion_time - p.arrival_time
p.waiting_time = p.turnaround_time - p.burst_time
p.response_time = p.start_time - p.arrival_time
# 带权周转时间 = 周转时间 / 服务时间
p.weighted_turnaround_time = p.turnaround_time / p.burst_time if p.burst_time > 0 else 0
def print_results(self, algorithm_name: str) -> Dict:
"""打印调度结果"""
n = len(self.results)
avg_waiting = sum(p.waiting_time for p in self.results) / n
avg_turnaround = sum(p.turnaround_time for p in self.results) / n
avg_weighted_turnaround = sum(p.weighted_turnaround_time for p in self.results) / n
avg_response = sum(p.response_time for p in self.results) / n
print(f"\n{'='*70}")
print(f"算法: {algorithm_name}")
print(f"{'='*70}")
print(f"{'PID':<6}{'到达':<6}{'服务':<6}{'开始':<6}{'完成':<6}"
f"{'等待':<6}{'周转':<6}{'带权周转':<10}{'响应':<6}")
print("-" * 70)
for p in self.results:
print(f"{p.pid:<6}{p.arrival_time:<6}{p.burst_time:<6}"
f"{p.start_time:<6}{p.completion_time:<6}"
f"{p.waiting_time:<6}{p.turnaround_time:<6}"
f"{p.weighted_turnaround_time:<10.2f}"
f"{p.response_time:<6}")
print("-" * 70)
print(f"{'平均等待时间:':<18} {avg_waiting:.2f}")
print(f"{'平均周转时间:':<18} {avg_turnaround:.2f}")
print(f"{'平均带权周转时间:':<18} {avg_weighted_turnaround:.2f}")
print(f"{'平均响应时间:':<18} {avg_response:.2f}")
# CPU 利用率
total_burst = sum(p.burst_time for p in self.results)
total_time = self.results[-1].completion_time - self.results[0].arrival_time
utilization = (total_burst / total_time) * 100 if total_time > 0 else 0
print(f"{'CPU 利用率:':<18} {utilization:.2f}%")
return {
'avg_waiting': avg_waiting,
'avg_turnaround': avg_turnaround,
'avg_weighted_turnaround': avg_weighted_turnaround,
'avg_response': avg_response,
'cpu_utilization': utilization
}
def generate_random_processes(
n: int = 10,
seed: Optional[int] = 42,
arrival_range: tuple = (0, 50),
burst_range: tuple = (1, 20),
priority_range: tuple = (1, 10)
) -> List[Process]:
"""
随机生成测试进程集
Args:
n: 进程数量
seed: 随机种子确保可复现
arrival_range: 到达时间范围 (min, max)
burst_range: 服务时间范围 (min, max)
priority_range: 优先级范围 (min, max)
Returns:
进程列表
"""
if seed is not None:
random.seed(seed)
processes = []
for i in range(n):
p = Process(
pid=f'P{i+1}',
arrival_time=random.randint(*arrival_range),
burst_time=random.randint(*burst_range),
priority=random.randint(*priority_range)
)
processes.append(p)
# 按到达时间排序
processes.sort(key=lambda p: p.arrival_time)
return processes
def print_processes(processes: List[Process], title: str = "测试数据"):
"""打印进程信息"""
print(f"\n{'='*60}")
print(f"{title}")
print(f"{'='*60}")
print(f"{'PID':<8}{'到达时间':<10}{'服务时间':<10}{'优先级':<10}")
print("-" * 60)
for p in processes:
print(f"{p.pid:<8}{p.arrival_time:<10}{p.burst_time:<10}{p.priority:<10}")
def print_comparison(results: Dict[str, Dict]):
"""打印算法比较结果"""
print("\n" + "="*90)
print("算法性能比较")
print("="*90)
print(f"{'算法':<10}{'平均等待':<12}{'平均周转':<12}{'平均带权周转':<14}{'平均响应':<12}{'CPU利用率':<12}")
print("-" * 90)
for name, metrics in results.items():
print(f"{name:<10}{metrics['avg_waiting']:<12.2f}{metrics['avg_turnaround']:<12.2f}"
f"{metrics.get('avg_weighted_turnaround', 0):<14.2f}"
f"{metrics['avg_response']:<12.2f}{metrics['cpu_utilization']:<12.2f}%")

43
experiment/code/fcfs.py Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env python3
"""
先来先服务调度算法 (FCFS)
First Come First Served
"""
from typing import List, Dict
from base import (
Process,
ProcessScheduler,
generate_random_processes,
print_processes
)
class FCFSScheduler(ProcessScheduler):
"""先来先服务调度 (First Come First Served)"""
def schedule(self) -> Dict:
"""FCFS 调度算法"""
# 按到达时间排序
ready_queue = sorted(self.processes, key=lambda p: (p.arrival_time, p.pid))
current_time = 0
for p in ready_queue:
if p.arrival_time > current_time:
current_time = p.arrival_time
p.start_time = current_time
current_time += p.burst_time
self.calculate_metrics(p, current_time)
self.results.append(p)
return self.print_results("FCFS (先来先服务)")
if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42)
print_processes(processes, "测试数据")
scheduler = FCFSScheduler(processes)
scheduler.schedule()

165
experiment/code/main.py Normal file
View File

@ -0,0 +1,165 @@
#!/usr/bin/env python3
"""
进程调度算法模拟器 - 主程序
运行方式:
python main.py # 默认小数据集测试
python main.py -n 100 # 生成 100 个随机进程
python main.py -n 1000 --seed 42 # 固定种子 42
python main.py -a P1,P2 # 指定运行的算法
python main.py --demo # 使用默认演示数据
参数说明:
-n, --num: 进程数量 (默认 5)
-s, --seed: 随机种子 (默认 42, 设为 None 则随机)
-a, --algo: 运行的算法 (默认全部)
--demo: 使用预设演示数据
"""
import argparse
from typing import List, Dict, Optional
from base import (
Process, ProcessScheduler,
generate_random_processes,
print_processes,
print_comparison
)
from fcfs import FCFSScheduler
from sjf import SJFScheduler
from rr import RoundRobinScheduler
from priority import PriorityScheduler
from mlfq import MLFQScheduler
# 预设演示数据
DEMO_PROCESSES = [
Process(pid='P1', arrival_time=0, burst_time=7, priority=3),
Process(pid='P2', arrival_time=2, burst_time=4, priority=1),
Process(pid='P3', arrival_time=4, burst_time=1, priority=4),
Process(pid='P4', arrival_time=5, burst_time=4, priority=2),
Process(pid='P5', arrival_time=6, burst_time=2, priority=3),
]
def get_algorithm_config() -> Dict:
"""算法配置:名称与调度器类的映射"""
return {
'FCFS': FCFSScheduler,
'SJF': lambda p: SJFScheduler(p, preemptive=False),
'SRTF': lambda p: SJFScheduler(p, preemptive=True),
'Priority': lambda p: PriorityScheduler(p, preemptive=False),
'RR': lambda p: RoundRobinScheduler(p, time_slice=4),
'MLFQ': lambda p: MLFQScheduler(p),
}
def run_all_algorithms(processes: List[Process], algorithms: Optional[List[str]] = None):
"""运行所有/指定调度算法并比较"""
# 深拷贝进程列表
original_processes = [Process(**p.__dict__) for p in processes]
# 默认运行所有算法
if algorithms is None:
algorithms = list(get_algorithm_config().keys())
results = {}
scheduler_map = get_algorithm_config()
for algo_name in algorithms:
if algo_name not in scheduler_map:
print(f"警告: 未知算法 '{algo_name}', 跳过")
continue
# 每次重新创建进程列表
process_list = [Process(**p.__dict__) for p in original_processes]
# 获取调度器
scheduler_class = scheduler_map[algo_name]
scheduler = scheduler_class(process_list)
# 运行调度
metrics = scheduler.schedule()
results[algo_name] = metrics
# 打印比较结果
print_comparison(results)
# 打印最优指标提示
print("\n" + "="*70)
print("指标分析")
print("="*70)
metrics_names = [
('avg_waiting', '平均等待时间'),
('avg_turnaround', '平均周转时间'),
('avg_weighted_turnaround', '平均带权周转时间'),
('avg_response', '平均响应时间'),
]
for metric_key, metric_name in metrics_names:
values = {name: m[metric_key] for name, m in results.items()}
best_algo = min(values, key=values.get)
print(f"{metric_name}: {best_algo} ({values[best_algo]:.2f}) 最优")
return results
def main():
parser = argparse.ArgumentParser(
description='进程调度算法模拟器',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__
)
parser.add_argument('-n', '--num', type=int, default=10,
help='随机生成的进程数量 (默认: 5)')
parser.add_argument('-s', '--seed', type=int, default=42,
help='随机种子 (默认: 42, 设为 None 则每次不同)')
parser.add_argument('-a', '--algo', type=str, default=None,
help='运行的算法,逗号分隔 (如: FCFS,SJF,RR)')
parser.add_argument('--demo', action='store_true',
help='使用预设演示数据')
parser.add_argument('--arrival', type=str, default='0,50',
help='到达时间范围 (格式: min,max)')
parser.add_argument('--burst', type=str, default='1,20',
help='服务时间范围 (格式: min,max)')
parser.add_argument('--priority', type=str, default='1,10',
help='优先级范围 (格式: min,max)')
args = parser.parse_args()
# 解析算法列表
algorithms = None
if args.algo:
algorithms = [a.strip() for a in args.algo.split(',')]
# 生成测试数据
if args.demo:
processes = DEMO_PROCESSES
print_processes(processes, "演示数据 (5 个进程)")
else:
# 解析范围
arrival_range = tuple(map(int, args.arrival.split(',')))
burst_range = tuple(map(int, args.burst.split(',')))
priority_range = tuple(map(int, args.priority.split(',')))
seed = args.seed if args.seed != -1 else None
processes = generate_random_processes(
n=args.num,
seed=seed,
arrival_range=arrival_range,
burst_range=burst_range,
priority_range=priority_range
)
title = f"随机测试数据 (n={args.num}, seed={args.seed if seed else 'None'})"
print_processes(processes, title)
# 运行算法
print(f"\n运行算法: {algorithms if algorithms else '全部'}")
run_all_algorithms(processes, algorithms)
if __name__ == "__main__":
main()

98
experiment/code/mlfq.py Normal file
View File

@ -0,0 +1,98 @@
#!/usr/bin/env python3
"""
多级反馈队列调度算法 (MLFQ)
Multilevel Feedback Queue
"""
from collections import deque
from typing import List, Dict
from base import (
Process,
ProcessScheduler,
generate_random_processes,
print_processes
)
class MLFQScheduler(ProcessScheduler):
"""多级反馈队列调度 (Multilevel Feedback Queue)"""
def __init__(self, processes: List[Process], queues: List[int] = None):
super().__init__(processes)
# 每层队列的时间片大小
self.queues = queues or [4, 8, 16]
self.aging_time = 50
def schedule(self) -> Dict:
"""MLFQ 调度算法"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
queues = [deque() for _ in self.queues]
current_time = 0
completed = 0
index = 0
while completed < len(processes):
while index < len(processes) and processes[index].arrival_time <= current_time:
queues[0].append(processes[index])
index += 1
# 老化
for i in range(1, len(queues)):
for p in list(queues[i]):
wait_time = current_time - p.arrival_time - (p.burst_time - p.remaining_time)
if wait_time > self.aging_time:
queues[i].remove(p)
queues[max(0, i-1)].append(p)
queue_idx = -1
for i in range(len(queues)):
if queues[i]:
queue_idx = i
break
if queue_idx >= 0:
p = queues[queue_idx].popleft()
if p.start_time == -1:
p.start_time = current_time
exec_time = min(self.queues[queue_idx], p.remaining_time)
p.remaining_time -= exec_time
current_time += exec_time
while index < len(processes) and processes[index].arrival_time <= current_time:
queues[0].append(processes[index])
index += 1
if p.remaining_time > 0:
if queue_idx < len(queues) - 1:
queues[queue_idx + 1].append(p)
else:
queues[queue_idx].append(p)
else:
self.calculate_metrics(p, current_time)
self.results.append(p)
completed += 1
else:
current_time += 1
return self.print_results(f"MLFQ (多级反馈队列, 队列时间片={self.queues})")
if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42)
print_processes(processes, "测试数据")
print("\n" + "="*60)
print("多级反馈队列调度 (默认配置)")
print("="*60)
scheduler1 = MLFQScheduler(processes)
scheduler1.schedule()
print("\n" + "="*60)
print("多级反馈队列调度 (自定义配置 [2, 5, 10])")
print("="*60)
scheduler2 = MLFQScheduler(processes, queues=[2, 5, 10])
scheduler2.schedule()

108
experiment/code/priority.py Normal file
View File

@ -0,0 +1,108 @@
#!/usr/bin/env python3
"""
优先级调度算法 (Priority Scheduling)
"""
from typing import List, Dict
from base import (
Process,
ProcessScheduler,
generate_random_processes,
print_processes
)
class PriorityScheduler(ProcessScheduler):
"""优先级调度"""
def __init__(self, processes: List[Process], preemptive: bool = False):
super().__init__(processes)
self.preemptive = preemptive
def schedule(self) -> Dict:
"""优先级调度算法"""
if self.preemptive:
return self.schedule_preemptive()
return self.schedule_non_preemptive()
def schedule_non_preemptive(self) -> Dict:
"""非抢占式优先级调度"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0
completed = 0
while completed < len(processes):
for p in processes:
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
ready_queue.append(p)
if ready_queue:
ready_queue.sort(key=lambda p: p.priority)
p = ready_queue.pop(0)
p.start_time = current_time
current_time += p.burst_time
self.calculate_metrics(p, current_time)
self.results.append(p)
completed += 1
else:
current_time += 1
return self.print_results("优先级调度 (非抢占)")
def schedule_preemptive(self) -> Dict:
"""抢占式优先级调度"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0
completed = 0
current_process = None
while completed < len(processes):
for p in processes:
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
ready_queue.append(p)
if ready_queue:
ready_queue.sort(key=lambda p: p.priority)
if current_process is None or current_process.priority > ready_queue[0].priority:
if current_process and current_process.remaining_time > 0:
ready_queue.append(current_process)
current_process = ready_queue.pop(0)
if current_process.start_time == -1:
current_process.start_time = current_time
current_process.remaining_time -= 1
current_time += 1
if current_process.remaining_time == 0:
self.calculate_metrics(current_process, current_time)
self.results.append(current_process)
completed += 1
current_process = None
else:
current_time += 1
return self.print_results("优先级调度 (抢占)")
if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42)
print_processes(processes, "测试数据")
print("\n" + "="*60)
print("非抢占式优先级调度")
print("="*60)
scheduler1 = PriorityScheduler(processes, preemptive=False)
scheduler1.schedule()
print("\n" + "="*60)
print("抢占式优先级调度")
print("="*60)
scheduler2 = PriorityScheduler(processes, preemptive=True)
scheduler2.schedule()

73
experiment/code/rr.py Normal file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""
时间片轮转调度算法 (RR)
Round Robin
"""
from collections import deque
from typing import List, Dict
from base import (
Process,
ProcessScheduler,
generate_random_processes,
print_processes
)
class RoundRobinScheduler(ProcessScheduler):
"""时间片轮转调度 (Round Robin)"""
def __init__(self, processes: List[Process], time_slice: int = 4):
super().__init__(processes)
self.time_slice = time_slice
def schedule(self) -> Dict:
"""RR 调度算法"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue = deque()
current_time = 0
completed = 0
index = 0
while completed < len(processes):
while index < len(processes) and processes[index].arrival_time <= current_time:
ready_queue.append(processes[index])
index += 1
if ready_queue:
p = ready_queue.popleft()
if p.start_time == -1:
p.start_time = current_time
exec_time = min(self.time_slice, p.remaining_time)
p.remaining_time -= exec_time
current_time += exec_time
while index < len(processes) and processes[index].arrival_time <= current_time:
ready_queue.append(processes[index])
index += 1
if p.remaining_time > 0:
ready_queue.append(p)
else:
self.calculate_metrics(p, current_time)
self.results.append(p)
completed += 1
else:
current_time += 1
return self.print_results(f"RR (时间片轮转, time_slice={self.time_slice})")
if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42)
print_processes(processes, "测试数据")
for ts in [2, 4, 8]:
print("\n" + "="*60)
print(f"时间片轮转 (time_slice={ts})")
print("="*60)
scheduler = RoundRobinScheduler(processes, time_slice=ts)
scheduler.schedule()

103
experiment/code/sjf.py Normal file
View File

@ -0,0 +1,103 @@
#!/usr/bin/env python3
"""
短作业优先调度算法 (SJF)
Shortest Job First / Shortest Remaining Time First (SRTF)
"""
from typing import List, Dict
from base import (
Process,
ProcessScheduler,
generate_random_processes,
print_processes
)
class SJFScheduler(ProcessScheduler):
"""短作业优先调度 (Shortest Job First)"""
def __init__(self, processes: List[Process], preemptive: bool = False):
super().__init__(processes)
self.preemptive = preemptive
def schedule(self) -> Dict:
"""SJF 调度算法"""
if self.preemptive:
return self.schedule_preemptive()
return self.schedule_non_preemptive()
def schedule_non_preemptive(self) -> Dict:
"""非抢占式 SJF"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0
completed = 0
while completed < len(processes):
for p in processes:
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
ready_queue.append(p)
if ready_queue:
ready_queue.sort(key=lambda p: p.burst_time)
p = ready_queue.pop(0)
p.start_time = current_time
current_time += p.burst_time
self.calculate_metrics(p, current_time)
self.results.append(p)
completed += 1
else:
current_time += 1
return self.print_results("SJF (短作业优先 - 非抢占)")
def schedule_preemptive(self) -> Dict:
"""抢占式 SJF (SRTF)"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0
completed = 0
while completed < len(processes):
for p in processes:
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
ready_queue.append(p)
if ready_queue:
ready_queue.sort(key=lambda p: p.remaining_time)
p = ready_queue[0]
if p.start_time == -1:
p.start_time = current_time
p.remaining_time -= 1
current_time += 1
if p.remaining_time == 0:
self.calculate_metrics(p, current_time)
self.results.append(p)
ready_queue.remove(p)
completed += 1
else:
current_time += 1
return self.print_results("SRTF (最短剩余时间优先 - 抢占)")
if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42)
print_processes(processes, "测试数据")
print("\n" + "="*60)
print("非抢占式 SJF")
print("="*60)
scheduler1 = SJFScheduler(processes, preemptive=False)
scheduler1.schedule()
print("\n" + "="*60)
print("抢占式 SJF (SRTF)")
print("="*60)
scheduler2 = SJFScheduler(processes, preemptive=True)
scheduler2.schedule()

View File

@ -179,6 +179,18 @@ stateDiagram-v2
2. **内核线程Kernel Thread**OS直接支持内核管理 2. **内核线程Kernel Thread**OS直接支持内核管理
3. **轻量级进程LWP**:一对一模型中的中间层 3. **轻量级进程LWP**:一对一模型中的中间层
## 6 进程调度算法
详见 [实验文档](../../experiment/README.md)
| 算法 | 原理 | 优点 | 缺点 |
|------|------|------|------|
| FCFS | 按到达顺序服务 | 简单、公平 | 平均等待时间长 |
| SJF | 最短作业优先 | 平均等待时间最优 | 可能导致长作业饥饿 |
| RR | 时间片轮转 | 响应时间短、公平 | 开销较大 |
| 优先级 | 高优先级先服务 | 可控性强 | 可能导致低优先级饥饿 |
| MLFQ | 多级反馈队列 | 综合性能好 | 实现复杂 |
--- ---
> **核心要点** > **核心要点**

View File

@ -0,0 +1,22 @@
# CPU 调度
## 1. 调度的层级
**高级调度** 又叫做作业调度从外存中选取一个或者多个作业为其分配内存设备IO等等资源。简而言之就是实现了内存与外存之间的调度让每个调度在生命周期中只用调入一次调出一次
**中级调度** 又叫做内存调度,将暂时被无法运行的进程挂起, 换出到外存
**低级调度** 按照特性算法从就绪队列中选择一个进程, 分配CPU 是操作系统中最频繁的调度, 通常几十微秒执行一次
## 2. 调度的时机
1. 创建新进程之后
2. 进程正常结束或者终止之后
3. 当进程因被如IO 信号量之类的操作阻塞之后
## 3. 调度的指标
1. CPU 利用率
2. 系统吞吐量
3. 带权周转时间
4. 等待时间
5. 响应时间