From f1034bf0444817eb9b1f2966b8659dee491a4bc1 Mon Sep 17 00:00:00 2001 From: ViperEkura <3081035982@qq.com> Date: Sun, 26 Apr 2026 16:41:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + experiment/README.md | 124 ++++++++++++++++++++++++++++++ experiment/code/base.py | 149 ++++++++++++++++++++++++++++++++++++ experiment/code/fcfs.py | 43 +++++++++++ experiment/code/main.py | 148 +++++++++++++++++++++++++++++++++++ experiment/code/mlfq.py | 98 ++++++++++++++++++++++++ experiment/code/priority.py | 108 ++++++++++++++++++++++++++ experiment/code/rr.py | 73 ++++++++++++++++++ experiment/code/sjf.py | 103 +++++++++++++++++++++++++ subjects/os/01_进程管理.md | 12 +++ 10 files changed, 859 insertions(+) create mode 100644 .gitignore create mode 100644 experiment/README.md create mode 100644 experiment/code/base.py create mode 100644 experiment/code/fcfs.py create mode 100644 experiment/code/main.py create mode 100644 experiment/code/mlfq.py create mode 100644 experiment/code/priority.py create mode 100644 experiment/code/rr.py create mode 100644 experiment/code/sjf.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/experiment/README.md b/experiment/README.md new file mode 100644 index 0000000..d4e6933 --- /dev/null +++ b/experiment/README.md @@ -0,0 +1,124 @@ +# 进程调度算法实验 + +## 实验目的 + +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$,服务时间为 $BT_i$: + +$$ +\text{周转时间} = CT_i - AT_i +$$ + +$$ +\text{等待时间} = WT_i = TAT_i - BT_i +$$ + +$$ +\text{响应时间} = RT_i = \text{首次运行时间} - AT_i +$$ + +## 算法公式 + +### 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) diff --git a/experiment/code/base.py b/experiment/code/base.py new file mode 100644 index 0000000..4c5c40d --- /dev/null +++ b/experiment/code/base.py @@ -0,0 +1,149 @@ +#!/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 + 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.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): + """计算进程性能指标""" + 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 + + 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_response = sum(p.response_time for p in self.results) / n + + print(f"\n{'='*60}") + print(f"算法: {algorithm_name}") + print(f"{'='*60}") + print(f"{'PID':<8}{'到达':<8}{'服务':<8}{'开始':<8}{'完成':<8}" + f"{'等待':<8}{'周转':<8}{'响应':<8}") + print("-" * 60) + + for p in self.results: + print(f"{p.pid:<8}{p.arrival_time:<8}{p.burst_time:<8}" + f"{p.start_time:<8}{p.completion_time:<8}" + f"{p.waiting_time:<8}{p.turnaround_time:<8}" + f"{p.response_time:<8}") + + print("-" * 60) + print(f"{'平均等待时间:':<15} {avg_waiting:.2f}") + print(f"{'平均周转时间:':<15} {avg_turnaround:.2f}") + print(f"{'平均响应时间:':<15} {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 利用率:':<15} {utilization:.2f}%") + + return { + 'avg_waiting': avg_waiting, + 'avg_turnaround': avg_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" + "="*60) + print("算法性能比较") + print("="*60) + print(f"{'算法':<15}{'平均等待':<12}{'平均周转':<12}{'平均响应':<12}{'CPU利用率':<12}") + print("-" * 60) + for name, metrics in results.items(): + print(f"{name:<15}{metrics['avg_waiting']:<12.2f}{metrics['avg_turnaround']:<12.2f}" + f"{metrics['avg_response']:<12.2f}{metrics['cpu_utilization']:<12.2f}%") diff --git a/experiment/code/fcfs.py b/experiment/code/fcfs.py new file mode 100644 index 0000000..50df866 --- /dev/null +++ b/experiment/code/fcfs.py @@ -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() diff --git a/experiment/code/main.py b/experiment/code/main.py new file mode 100644 index 0000000..cbe39b0 --- /dev/null +++ b/experiment/code/main.py @@ -0,0 +1,148 @@ +#!/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) + + 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() diff --git a/experiment/code/mlfq.py b/experiment/code/mlfq.py new file mode 100644 index 0000000..13fd31a --- /dev/null +++ b/experiment/code/mlfq.py @@ -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() diff --git a/experiment/code/priority.py b/experiment/code/priority.py new file mode 100644 index 0000000..d337b80 --- /dev/null +++ b/experiment/code/priority.py @@ -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() diff --git a/experiment/code/rr.py b/experiment/code/rr.py new file mode 100644 index 0000000..059b31c --- /dev/null +++ b/experiment/code/rr.py @@ -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() diff --git a/experiment/code/sjf.py b/experiment/code/sjf.py new file mode 100644 index 0000000..c3bbf3e --- /dev/null +++ b/experiment/code/sjf.py @@ -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() diff --git a/subjects/os/01_进程管理.md b/subjects/os/01_进程管理.md index e1a6ed4..fcef0ac 100644 --- a/subjects/os/01_进程管理.md +++ b/subjects/os/01_进程管理.md @@ -179,6 +179,18 @@ stateDiagram-v2 2. **内核线程(Kernel Thread)**:OS直接支持,内核管理 3. **轻量级进程(LWP)**:一对一模型中的中间层 +## 6 进程调度算法 + +详见 [实验文档](../../experiment/README.md) + +| 算法 | 原理 | 优点 | 缺点 | +|------|------|------|------| +| FCFS | 按到达顺序服务 | 简单、公平 | 平均等待时间长 | +| SJF | 最短作业优先 | 平均等待时间最优 | 可能导致长作业饥饿 | +| RR | 时间片轮转 | 响应时间短、公平 | 开销较大 | +| 优先级 | 高优先级先服务 | 可控性强 | 可能导致低优先级饥饿 | +| MLFQ | 多级反馈队列 | 综合性能好 | 实现复杂 | + --- > **核心要点**: