feat: 增加周转时间部分的设置
This commit is contained in:
parent
6031dc3198
commit
eb1de7b3d1
|
|
@ -0,0 +1 @@
|
|||
__pycache__
|
||||
|
|
@ -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)
|
||||
|
|
@ -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}%")
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -179,6 +179,18 @@ stateDiagram-v2
|
|||
2. **内核线程(Kernel Thread)**:OS直接支持,内核管理
|
||||
3. **轻量级进程(LWP)**:一对一模型中的中间层
|
||||
|
||||
## 6 进程调度算法
|
||||
|
||||
详见 [实验文档](../../experiment/README.md)
|
||||
|
||||
| 算法 | 原理 | 优点 | 缺点 |
|
||||
|------|------|------|------|
|
||||
| FCFS | 按到达顺序服务 | 简单、公平 | 平均等待时间长 |
|
||||
| SJF | 最短作业优先 | 平均等待时间最优 | 可能导致长作业饥饿 |
|
||||
| RR | 时间片轮转 | 响应时间短、公平 | 开销较大 |
|
||||
| 优先级 | 高优先级先服务 | 可控性强 | 可能导致低优先级饥饿 |
|
||||
| MLFQ | 多级反馈队列 | 综合性能好 | 实现复杂 |
|
||||
|
||||
---
|
||||
|
||||
> **核心要点**:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# CPU 调度
|
||||
|
||||
## 1. 调度的层级
|
||||
|
||||
**高级调度** :又叫做作业调度,从外存中选取一个或者多个作业,为其分配内存,设备,IO等等资源。简而言之就是实现了内存与外存之间的调度,让每个调度在生命周期中只用调入一次调出一次
|
||||
**中级调度**: 又叫做内存调度,将暂时被无法运行的进程挂起, 换出到外存
|
||||
**低级调度**: 按照特性算法从就绪队列中选择一个进程, 分配CPU, 是操作系统中最频繁的调度, 通常几十微秒执行一次
|
||||
|
||||
## 2. 调度的时机
|
||||
|
||||
1. 创建新进程之后
|
||||
2. 进程正常结束或者终止之后
|
||||
3. 当进程因被如IO, 信号量之类的操作阻塞之后
|
||||
|
||||
## 3. 调度的指标
|
||||
|
||||
1. CPU 利用率
|
||||
2. 系统吞吐量
|
||||
3. 带权周转时间
|
||||
4. 等待时间
|
||||
5. 响应时间
|
||||
|
||||
Loading…
Reference in New Issue