refactor: 修改实验步骤

This commit is contained in:
ViperEkura 2026-04-30 15:43:18 +08:00
parent 56e3cc9bf4
commit 001416e399
8 changed files with 852 additions and 340 deletions

View File

@ -10,11 +10,32 @@ from typing import List, Dict, Optional
@dataclass @dataclass
class Process: class Process:
"""进程数据结构""" """进程数据结构
新增 IO 模拟字段:
cpu_bursts: CPU 计算时间段列表 (交替: CPU->IO->CPU->IO...)
io_bursts: IO 操作时间段列表
io_wait: 进程在 IO 设备上等待的时间 (阻塞时间)
示例:
cpu_bursts = [5, 3, 2] # 3段CPU计算时间
io_bursts = [2, 1] # 2次IO操作
进程执行顺序: CPU(5) -> IO(2) -> CPU(3) -> IO(1) -> CPU(2)
"""
pid: str pid: str
arrival_time: int = 0 arrival_time: int = 0
burst_time: int = 0 burst_time: int = 0 # 总CPU时间 = sum(cpu_bursts)
priority: int = 0 # 数值越小优先级越高 priority: int = 0 # 数值越小优先级越高
# ========== 新增 IO 模拟字段 ==========
cpu_bursts: List[int] = field(default_factory=list) # CPU计算时间段
io_bursts: List[int] = field(default_factory=list) # IO操作时间段
io_wait: int = 0 # IO设备等待时间
is_io_bound: bool = False # 是否为IO密集型进程
starts_with_io: bool = False # 是否以IO开始默认False=先CPU
# =====================================
# 调度相关状态
remaining_time: int = field(default=0) remaining_time: int = field(default=0)
start_time: int = -1 start_time: int = -1
completion_time: int = 0 completion_time: int = 0
@ -22,9 +43,28 @@ class Process:
turnaround_time: int = 0 turnaround_time: int = 0
weighted_turnaround_time: float = 0.0 # 带权周转时间 = 周转时间/服务时间 weighted_turnaround_time: float = 0.0 # 带权周转时间 = 周转时间/服务时间
response_time: int = 0 response_time: int = 0
io_blocked_time: int = 0 # 因等待IO而阻塞的时间
def __post_init__(self): def __post_init__(self):
self.remaining_time = self.burst_time self.remaining_time = self.burst_time
# 如果没有指定 cpu_bursts使用 burst_time 作为单段CPU时间
if not self.cpu_bursts and self.burst_time > 0:
self.cpu_bursts = [self.burst_time]
@property
def total_cpu_time(self) -> int:
"""总CPU计算时间"""
return sum(self.cpu_bursts) if self.cpu_bursts else self.burst_time
@property
def total_io_time(self) -> int:
"""总IO操作时间"""
return sum(self.io_bursts) if self.io_bursts else 0
@property
def num_io_operations(self) -> int:
"""IO操作次数"""
return len(self.io_bursts)
def reset(self): def reset(self):
"""重置进程状态""" """重置进程状态"""
@ -35,18 +75,92 @@ class Process:
self.turnaround_time = 0 self.turnaround_time = 0
self.weighted_turnaround_time = 0.0 self.weighted_turnaround_time = 0.0
self.response_time = 0 self.response_time = 0
self.io_blocked_time = 0
class ProcessScheduler: class ProcessScheduler:
"""进程调度器基类""" """进程调度器基类 (支持IO模拟)"""
# 进程状态
STATUS_NEW = 'NEW'
STATUS_READY = 'READY'
STATUS_RUNNING = 'RUNNING'
STATUS_IO_WAIT = 'IO_WAIT' # 等待IO完成
STATUS_TERMINATED = 'TERMINATED'
def __init__(self, processes: List[Process]): def __init__(self, processes: List[Process]):
self.processes = [p for p in processes] self.processes = [p for p in processes]
self.results: List[Process] = [] self.results: List[Process] = []
self.gantt_chart: List[tuple] = [] # 甘特图记录 (时间, PID, 事件)
# IO 模拟相关
self.io_queue: List[Process] = [] # IO 等待队列 (等待IO完成的进程)
self.io_completion_events: List[tuple] = [] # IO 完成事件 (时间, 进程)
def init_process(self, p: Process, current_time: int):
"""初始化进程状态"""
p.status = self.STATUS_READY
p.current_cpu_idx = 0 # 当前执行的 cpu_burst 索引
p.current_io_idx = -1 # 当前等待的 io_burst 索引 (-1表示未进入IO)
p.remaining_cpu_time = sum(p.cpu_bursts) if p.cpu_bursts else p.burst_time
p.io_wait_time = 0 # 累计IO等待时间
if p.start_time == -1:
p.start_time = current_time
def execute_cpu(self, p: Process, time_slice: int, current_time: int):
"""执行一段 CPU burst"""
if p.current_cpu_idx >= len(p.cpu_bursts):
return 0 # 没有更多CPU burst
cpu_burst = p.cpu_bursts[p.current_cpu_idx]
execute_time = min(time_slice, cpu_burst)
p.remaining_cpu_time -= execute_time
# 记录甘特图
self.gantt_chart.append((current_time, p.pid, 'CPU', execute_time))
if execute_time >= cpu_burst:
# CPU burst 执行完毕
p.current_cpu_idx += 1
# 检查是否有对应的 IO burst
if p.current_cpu_idx - 1 < len(p.io_bursts):
# 进入 IO 等待
io_time = p.io_bursts[p.current_cpu_idx - 1]
p.current_io_idx = p.current_cpu_idx - 1
p.io_burst_remaining = io_time
p.status = self.STATUS_IO_WAIT
self.io_completion_events.append((current_time + io_time, p))
return execute_time
# 没有更多 burst进程结束
p.status = self.STATUS_TERMINATED
p.completion_time = current_time + execute_time
self.results.append(p)
return execute_time
else:
# 时间片用完但 CPU burst 还没完
return execute_time
def handle_io_completions(self, current_time: int):
"""处理当前时刻完成的 IO 事件"""
completed = []
for i, (io_time, p) in enumerate(self.io_completion_events):
if io_time <= current_time:
completed.append(i)
p.status = self.STATUS_READY
p.io_wait_time += io_time - (current_time - p.io_burst_remaining)
# 移除已处理的事件 (倒序删除避免索引问题)
for i in reversed(completed):
self.io_completion_events.pop(i)
return completed
def calculate_metrics(self, p: Process, current_time: int): def calculate_metrics(self, p: Process, current_time: int):
""" """
计算进程性能指标 计算进程性能指标 (支持IO模拟)
周转时间 (Turnaround Time): CT - AT 周转时间 (Turnaround Time): CT - AT
进程从提交到完成的总时间 进程从提交到完成的总时间
@ -57,57 +171,98 @@ class ProcessScheduler:
等待时间 (Waiting Time): TAT - BT 等待时间 (Waiting Time): TAT - BT
进程在就绪队列中等待的时间总和 进程在就绪队列中等待的时间总和
注意: 这里只计算CPU等待时间不包括IO等待时间
响应时间 (Response Time): ST - AT 响应时间 (Response Time): ST - AT
从提交到首次运行的时间 从提交到首次运行的时间
""" """
if p.status == self.STATUS_TERMINATED:
p.completion_time = current_time if p.completion_time == 0 else p.completion_time
else:
p.completion_time = current_time p.completion_time = current_time
p.turnaround_time = p.completion_time - p.arrival_time p.turnaround_time = p.completion_time - p.arrival_time
p.waiting_time = p.turnaround_time - p.burst_time # 等待时间 = 周转时间 - 总CPU时间 - IO等待时间
p.response_time = p.start_time - p.arrival_time p.waiting_time = p.turnaround_time - p.total_cpu_time - p.io_wait_time
if p.waiting_time < 0:
p.waiting_time = 0
p.response_time = p.start_time - p.arrival_time if p.start_time > 0 else 0
# 带权周转时间 = 周转时间 / 服务时间 # 带权周转时间 = 周转时间 / 服务时间
p.weighted_turnaround_time = p.turnaround_time / p.burst_time if p.burst_time > 0 else 0 p.weighted_turnaround_time = p.turnaround_time / p.burst_time if p.burst_time > 0 else 0
p.io_wait = p.io_wait_time
def print_results(self, algorithm_name: str) -> Dict: def print_results(self, algorithm_name: str) -> Dict:
"""打印调度结果""" """打印调度结果 (支持IO模拟)"""
n = len(self.results) n = len(self.results)
if n == 0:
return {}
avg_waiting = sum(p.waiting_time for p in self.results) / n 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_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_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 avg_response = sum(p.response_time for p in self.results) / n
print(f"\n{'='*70}") # 计算IO相关指标
total_io_time = sum(p.total_io_time for p in self.results)
total_io_wait = sum(p.io_wait for p in self.results)
avg_io_wait = total_io_wait / n if n > 0 else 0
io_bound_count = sum(1 for p in self.results if p.is_io_bound)
print(f"\n{'='*85}")
print(f"算法: {algorithm_name}") print(f"算法: {algorithm_name}")
print(f"{'='*70}") print(f"{'='*85}")
print(f"{'PID':<6}{'到达':<6}{'服务':<6}{'开始':<6}{'完成':<6}" print(f"{'PID':<6}{'类型':<6}{'起始':<6}{'到达':<6}{'服务':<6}{'IO次数':<6}{'IO时间':<8}"
f"{'等待':<6}{'周转':<6}{'带权周转':<10}{'响应':<6}") f"{'周转':<6}{'CPU等待':<8}{'IO等待':<8}{'响应':<6}")
print("-" * 70) print("-" * 85)
for p in self.results: for p in self.results:
print(f"{p.pid:<6}{p.arrival_time:<6}{p.burst_time:<6}" proc_type = "IO" if p.is_io_bound else "CPU"
f"{p.start_time:<6}{p.completion_time:<6}" start_phase = "IO" if p.starts_with_io else "CPU"
f"{p.waiting_time:<6}{p.turnaround_time:<6}" print(f"{p.pid:<6}{proc_type:<6}{start_phase:<6}{p.arrival_time:<6}{p.burst_time:<6}"
f"{p.weighted_turnaround_time:<10.2f}" f"{p.num_io_operations:<6}{p.total_io_time:<8}"
f"{p.response_time:<6}") f"{p.turnaround_time:<6}{p.waiting_time:<8}{p.io_wait:<8}{p.response_time:<6}")
print("-" * 70) print("-" * 85)
print(f"{'平均等待时间:':<18} {avg_waiting:.2f}") print(f"{'平均等待时间:':<22} {avg_waiting:.2f}")
print(f"{'平均周转时间:':<18} {avg_turnaround:.2f}") print(f"{'平均周转时间:':<22} {avg_turnaround:.2f}")
print(f"{'平均带权周转时间:':<18} {avg_weighted_turnaround:.2f}") print(f"{'平均带权周转时间:':<22} {avg_weighted_turnaround:.2f}")
print(f"{'平均响应时间:':<18} {avg_response:.2f}") print(f"{'平均响应时间:':<22} {avg_response:.2f}")
# CPU 利用率 # CPU 利用率计算 (考虑IO模拟)
total_burst = sum(p.burst_time for p in self.results) total_cpu_time = sum(p.total_cpu_time for p in self.results) # 纯CPU时间
total_time = self.results[-1].completion_time - self.results[0].arrival_time total_time = self.results[-1].completion_time - self.results[0].arrival_time
utilization = (total_burst / total_time) * 100 if total_time > 0 else 0 # CPU利用率 = CPU执行时间 / 总时间
print(f"{'CPU 利用率:':<18} {utilization:.2f}%") # 注意: IO期间CPU可以运行其他进程所以利用率应该更高
utilization = (total_cpu_time / total_time) * 100 if total_time > 0 else 0
# 计算CPU实际空闲时间
cpu_busy_time = len(self.gantt_chart) * 1 # 每个时间单位被计入
# 简化: 空闲时间 = 总时间 - CPU总执行时间
idle_time = total_time - total_cpu_time
print(f"\n{'='*85}")
print("性能统计")
print("-" * 85)
print(f"{'总执行时间:':<22} {total_time}")
print(f"{'总CPU时间:':<22} {total_cpu_time}")
print(f"{'CPU利用率:':<22} {utilization:.2f}%")
print(f"{'总IO时间:':<22} {total_io_time}")
print(f"{'总IO等待时间:':<22} {total_io_wait}")
print(f"{'平均IO等待:':<22} {avg_io_wait:.2f}")
print(f"{'IO密集型进程:':<22} {io_bound_count}/{n}")
return { return {
'avg_waiting': avg_waiting, 'avg_waiting': avg_waiting,
'avg_turnaround': avg_turnaround, 'avg_turnaround': avg_turnaround,
'avg_weighted_turnaround': avg_weighted_turnaround, 'avg_weighted_turnaround': avg_weighted_turnaround,
'avg_response': avg_response, 'avg_response': avg_response,
'cpu_utilization': utilization 'cpu_utilization': utilization,
'total_time': total_time,
'total_cpu_time': total_cpu_time,
'total_io_time': total_io_time,
'total_io_wait': total_io_wait,
'avg_io_wait': avg_io_wait,
'io_bound_count': io_bound_count
} }
@ -116,10 +271,14 @@ def generate_random_processes(
seed: Optional[int] = 42, seed: Optional[int] = 42,
arrival_range: tuple = (0, 50), arrival_range: tuple = (0, 50),
burst_range: tuple = (1, 20), burst_range: tuple = (1, 20),
priority_range: tuple = (1, 10) priority_range: tuple = (1, 10),
io_probability: float = 0.5, # 进程有IO操作的概率
io_count_range: tuple = (1, 4), # IO操作次数范围
io_time_range: tuple = (3, 15), # 每次IO时间范围
io_first_prob: float = 0.0, # 以IO开始的概率 (0.0=全部先CPU, 1.0=全部先IO)
) -> List[Process]: ) -> List[Process]:
""" """
随机生成测试进程集 随机生成测试进程集 (支持IO模拟)
Args: Args:
n: 进程数量 n: 进程数量
@ -127,20 +286,95 @@ def generate_random_processes(
arrival_range: 到达时间范围 (min, max) arrival_range: 到达时间范围 (min, max)
burst_range: 服务时间范围 (min, max) burst_range: 服务时间范围 (min, max)
priority_range: 优先级范围 (min, max) priority_range: 优先级范围 (min, max)
io_probability: 进程有IO操作的概率 (0.0-1.0)
io_count_range: IO操作次数范围 (min, max)
io_time_range: 每次IO时间范围 (min, max)
io_first_prob: 以IO开始的概率 (0.0=全部先CPU, 1.0=全部先IO, 0.5=随机)
Returns: Returns:
进程列表 进程列表
示例:
# 生成10个进程50%有IO全部先CPU
processes = generate_random_processes(n=10, io_probability=0.5)
# 生成IO密集型场景30%以IO开始
processes = generate_random_processes(n=10, io_probability=0.8, io_first_prob=0.3)
""" """
if seed is not None: if seed is not None:
random.seed(seed) random.seed(seed)
processes = [] processes = []
for i in range(n): for i in range(n):
# 生成基本属性
arrival = random.randint(*arrival_range)
total_burst = random.randint(*burst_range)
priority = random.randint(*priority_range)
# 确定是否为IO密集型进程
is_io_bound = random.random() < io_probability
# 确定起始阶段
starts_with_io = random.random() < io_first_prob if io_first_prob > 0 else False
cpu_bursts = []
io_bursts = []
if is_io_bound:
# IO密集型: 短CPU计算 + 长IO等待
num_io = random.randint(*io_count_range)
if starts_with_io:
# 先IO再CPU: IO -> CPU -> IO -> CPU -> ...
for j in range(num_io):
# IO burst
io_time = random.randint(*io_time_range)
io_bursts.append(io_time)
# CPU burst
remaining = total_burst - sum(cpu_bursts)
max_cpu = min(3, remaining - (num_io - j - 1))
if max_cpu < 1:
max_cpu = 1
cpu_time = random.randint(1, max_cpu)
cpu_bursts.append(cpu_time)
# 最后一段CPU
remaining = total_burst - sum(cpu_bursts)
if remaining > 0:
cpu_bursts.append(remaining)
else:
# 先CPU再IO: CPU -> IO -> CPU -> IO -> ...
remaining = total_burst
for j in range(num_io + 1):
if j < num_io:
# CPU burst: 短时间 (1-3)
max_cpu = min(3, remaining - (num_io - j))
if max_cpu < 1:
max_cpu = 1
cpu_time = random.randint(1, max_cpu)
else:
# 最后一段CPU时间
cpu_time = remaining
if cpu_time > 0:
cpu_bursts.append(cpu_time)
remaining -= cpu_time
if j < num_io and remaining > 0:
# IO burst: 较长时间 (长IO等待)
io_time = random.randint(*io_time_range)
io_bursts.append(io_time)
else:
# CPU密集型: 长CPU计算 + 无/少IO
cpu_bursts = [total_burst]
p = Process( p = Process(
pid=f'P{i+1}', pid=f'P{i+1}',
arrival_time=random.randint(*arrival_range), arrival_time=arrival,
burst_time=random.randint(*burst_range), burst_time=total_burst,
priority=random.randint(*priority_range) priority=priority,
cpu_bursts=cpu_bursts,
io_bursts=io_bursts,
is_io_bound=is_io_bound,
starts_with_io=starts_with_io
) )
processes.append(p) processes.append(p)
@ -150,24 +384,64 @@ def generate_random_processes(
def print_processes(processes: List[Process], title: str = "测试数据"): def print_processes(processes: List[Process], title: str = "测试数据"):
"""打印进程信息""" """打印进程信息 (包含IO模拟信息)"""
print(f"\n{'='*60}") print(f"\n{'='*80}")
print(f"{title}") print(f"{title}")
print(f"{'='*60}") print(f"{'='*80}")
print(f"{'PID':<8}{'到达时间':<10}{'服务时间':<10}{'优先级':<10}") print(f"{'PID':<6}{'类型':<6}{'起始':<6}{'到达':<6}{'服务':<6}{'IO次数':<6}{'IO时间':<8}{'优先级':<6}")
print("-" * 60) print("-" * 80)
io_bound_count = 0
io_first_count = 0
for p in processes: for p in processes:
print(f"{p.pid:<8}{p.arrival_time:<10}{p.burst_time:<10}{p.priority:<10}") proc_type = "IO" if p.is_io_bound else "CPU"
start_phase = "IO" if p.starts_with_io else "CPU"
if p.is_io_bound:
io_bound_count += 1
if p.starts_with_io:
io_first_count += 1
io_time = p.total_io_time
print(f"{p.pid:<6}{proc_type:<6}{start_phase:<6}{p.arrival_time:<6}{p.burst_time:<6}"
f"{p.num_io_operations:<6}{io_time:<8}{p.priority:<6}")
print("-" * 80)
print(f"总进程数: {len(processes)}, CPU密集型: {len(processes)-io_bound_count}, IO密集型: {io_bound_count}")
print(f"起始阶段: 先CPU: {len(processes)-io_first_count}, 先IO: {io_first_count}")
# 详细显示有IO的进程的CPU和IO burst
io_processes = [p for p in processes if p.io_bursts]
if io_processes:
print(f"\n{'='*80}")
print("IO 操作详细 (执行模式)")
print("-" * 80)
for p in io_processes:
# 构建执行模式字符串
pattern = []
if p.starts_with_io:
# 先IO再CPU
for i, io in enumerate(p.io_bursts):
pattern.append(f"IO({io})")
if i < len(p.cpu_bursts):
pattern.append(f"CPU({p.cpu_bursts[i]})")
else:
# 先CPU再IO
for i, cpu in enumerate(p.cpu_bursts):
pattern.append(f"CPU({cpu})")
if i < len(p.io_bursts):
pattern.append(f"IO({p.io_bursts[i]})")
print(f"{p.pid}: {' -> '.join(pattern)}")
def print_comparison(results: Dict[str, Dict]): def print_comparison(results: Dict[str, Dict]):
"""打印算法比较结果""" """打印算法比较结果 (包含IO指标)"""
print("\n" + "="*90) print("\n" + "="*100)
print("算法性能比较") print("算法性能比较")
print("="*90) print("="*100)
print(f"{'算法':<10}{'平均等待':<12}{'平均周转':<12}{'平均带权周转':<14}{'平均响应':<12}{'CPU利用率':<12}") print(f"{'算法':<8}{'平均等待':<10}{'平均周转':<10}{'平均带权周转':<12}{'平均响应':<10}{'CPU利用率':<10}{'IO阻塞':<10}")
print("-" * 90) print("-" * 100)
for name, metrics in results.items(): for name, metrics in results.items():
print(f"{name:<10}{metrics['avg_waiting']:<12.2f}{metrics['avg_turnaround']:<12.2f}" print(f"{name:<8}{metrics['avg_waiting']:<10.2f}{metrics['avg_turnaround']:<10.2f}"
f"{metrics.get('avg_weighted_turnaround', 0):<14.2f}" f"{metrics.get('avg_weighted_turnaround', 0):<12.2f}"
f"{metrics['avg_response']:<12.2f}{metrics['cpu_utilization']:<12.2f}%") f"{metrics['avg_response']:<10.2f}"
f"{metrics['cpu_utilization']:<10.2f}%"
f"{metrics.get('avg_io_wait', 0):<10.2f}")

View File

@ -2,9 +2,12 @@
""" """
先来先服务调度算法 (FCFS) 先来先服务调度算法 (FCFS)
First Come First Served First Come First Served
支持 IO 模拟
""" """
from typing import List, Dict from typing import List, Dict, Tuple
from collections import deque
import heapq
from base import ( from base import (
Process, Process,
@ -15,28 +18,97 @@ from base import (
class FCFSScheduler(ProcessScheduler): class FCFSScheduler(ProcessScheduler):
"""先来先服务调度 (First Come First Served)""" """先来先服务调度 (First Come First Served)
支持 IO 模拟:
- 进程执行一个 CPU burst 后进入 IO 等待
- IO 等待期间 CPU 可以调度其他就绪进程
- IO 完成时进程回到就绪队列
"""
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""FCFS 调度算法""" """FCFS 调度算法 (支持IO模拟)"""
# 按到达时间排序 all_processes = list(self.processes)
ready_queue = sorted(self.processes, key=lambda p: (p.arrival_time, p.pid)) for p in all_processes:
self.init_process(p, p.arrival_time)
# 事件队列: (时间, 事件类型, 唯一ID, 进程)
events = []
for p in all_processes:
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
ready_queue = deque() # 就绪队列 (按到达顺序)
completed = []
current_time = 0 current_time = 0
for p in ready_queue: last_processed_time = 0
if p.arrival_time > current_time:
current_time = p.arrival_time
p.start_time = current_time while len(completed) < len(all_processes):
current_time += p.burst_time # 1. 处理所有当前时刻的事件
self.calculate_metrics(p, current_time) while events and events[0][0] <= current_time:
self.results.append(p) event_time, event_type, uid, p = heapq.heappop(events)
if event_type == 'arrival':
p.status = self.STATUS_READY
ready_queue.append(p)
elif event_type == 'io_complete':
if p.status == self.STATUS_IO_WAIT:
p.status = self.STATUS_READY
ready_queue.append(p)
# 2. 如果就绪队列为空,推进时间到下一个事件
if not ready_queue:
if events:
current_time = events[0][0]
continue
else:
break
# 3. FCFS: 选择队首进程
current_process = ready_queue.popleft()
if current_process.start_time == -1:
current_process.start_time = current_time
current_process.status = self.STATUS_RUNNING
# 4. 执行 CPU burst
if current_process.current_cpu_idx < len(current_process.cpu_bursts):
cpu_burst = current_process.cpu_bursts[current_process.current_cpu_idx]
self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
current_time += cpu_burst
current_process.remaining_cpu_time -= cpu_burst
current_process.current_cpu_idx += 1
# 5. 检查是否有 IO burst
io_idx = current_process.current_cpu_idx - 1
if io_idx < len(current_process.io_bursts):
# 进入 IO 等待,添加 IO 完成事件
io_time = current_process.io_bursts[io_idx]
current_process.status = self.STATUS_IO_WAIT
io_complete_time = current_time + io_time
heapq.heappush(events, (io_complete_time, 'io_complete', id(current_process), current_process))
else:
# 进程完成
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
else:
# 进程完成
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
self.results = completed
return self.print_results("FCFS (先来先服务)") return self.print_results("FCFS (先来先服务)")
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5, io_first_prob=0.3)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
scheduler = FCFSScheduler(processes) scheduler = FCFSScheduler(processes)

View File

@ -1,10 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
高响应比优先调度算法 (HRRN) 高响应比优先调度算法 (HRRN)
Highest Response Ratio Next 支持 IO 模拟
""" """
from typing import List, Dict from typing import List, Dict
import heapq
from base import ( from base import (
Process, Process,
@ -15,57 +16,95 @@ from base import (
class HRRNScheduler(ProcessScheduler): class HRRNScheduler(ProcessScheduler):
""" """高响应比优先调度
高响应比优先调度 (Highest Response Ratio Next)
响应比 = (等待时间 + 服务时间) / 服务时间 响应比 = (等待时间 + 服务时间) / 服务时间
= 1 + 等待时间 / 服务时间
特点 支持 IO 模拟
- 非抢占式
- 综合考虑了等待时间和服务时间
- 避免长作业饥饿问题
""" """
def calculate_response_ratio(self, p: Process, current_time: int) -> float:
"""计算响应比"""
waiting_time = current_time - p.arrival_time
return 1 + (waiting_time / p.burst_time) if p.burst_time > 0 else float('inf')
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""HRRN 调度算法""" """HRRN 调度算法 (支持IO模拟)"""
processes = sorted(self.processes, key=lambda p: p.arrival_time) all_processes = list(self.processes)
ready_queue: List[Process] = [] for p in all_processes:
current_time = 0 self.init_process(p, p.arrival_time)
completed = 0
while completed < len(processes): events = []
# 添加所有到达的进程 for p in all_processes:
for p in processes: heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
ready_queue = [] # (response_ratio, pid, process)
completed = []
current_time = 0
while len(completed) < len(all_processes):
while events and events[0][0] <= current_time:
event_time, event_type, uid, p = heapq.heappop(events)
if event_type == 'arrival':
p.status = self.STATUS_READY
ready_queue.append(p)
elif event_type == 'io_complete':
if p.status == self.STATUS_IO_WAIT:
p.status = self.STATUS_READY
ready_queue.append(p) ready_queue.append(p)
if ready_queue: if not ready_queue:
# 计算每个进程的响应比,选择最高的 if events:
ready_queue.sort( current_time = events[0][0]
key=lambda p: self.calculate_response_ratio(p, current_time), continue
reverse=True # 响应比高优先
)
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: else:
current_time += 1 break
# 计算响应比
for p in ready_queue:
wait_time = current_time - p.arrival_time
remaining = p.remaining_cpu_time if p.remaining_cpu_time > 0 else p.total_cpu_time
if remaining > 0:
p.response_ratio = (wait_time + remaining) / remaining
else:
p.response_ratio = float('inf')
ready_queue.sort(key=lambda x: (-x.response_ratio, id(x)))
current_process = ready_queue.pop(0)
if current_process.start_time == -1:
current_process.start_time = current_time
current_process.status = self.STATUS_RUNNING
if current_process.current_cpu_idx < len(current_process.cpu_bursts):
cpu_burst = current_process.cpu_bursts[current_process.current_cpu_idx]
self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
current_time += cpu_burst
current_process.remaining_cpu_time -= cpu_burst
current_process.current_cpu_idx += 1
io_idx = current_process.current_cpu_idx - 1
if io_idx < len(current_process.io_bursts):
io_time = current_process.io_bursts[io_idx]
current_process.status = self.STATUS_IO_WAIT
heapq.heappush(events, (current_time + io_time, 'io_complete', id(current_process), current_process))
else:
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
else:
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
self.results = completed
return self.print_results("HRRN (高响应比优先)") return self.print_results("HRRN (高响应比优先)")
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
scheduler = HRRNScheduler(processes) scheduler = HRRNScheduler(processes)

View File

@ -32,13 +32,21 @@ from mlfq import MLFQScheduler
from hrrn import HRRNScheduler from hrrn import HRRNScheduler
# 预设演示数据 # 预设演示数据 (包含IO模拟)
DEMO_PROCESSES = [ DEMO_PROCESSES = [
Process(pid='P1', arrival_time=0, burst_time=7, priority=3), # CPU密集型进程
Process(pid='P2', arrival_time=2, burst_time=4, priority=1), Process(pid='P1', arrival_time=0, burst_time=7, priority=3,
Process(pid='P3', arrival_time=4, burst_time=1, priority=4), cpu_bursts=[7], io_bursts=[], is_io_bound=False),
Process(pid='P4', arrival_time=5, burst_time=4, priority=2), # IO密集型进程: CPU -> IO -> CPU -> IO -> CPU
Process(pid='P5', arrival_time=6, burst_time=2, priority=3), Process(pid='P2', arrival_time=2, burst_time=10, priority=1,
cpu_bursts=[3, 2, 3], io_bursts=[5, 4], is_io_bound=True),
Process(pid='P3', arrival_time=4, burst_time=1, priority=4,
cpu_bursts=[1], io_bursts=[], is_io_bound=False),
# IO密集型进程
Process(pid='P4', arrival_time=5, burst_time=8, priority=2,
cpu_bursts=[2, 2, 2], io_bursts=[6, 5], is_io_bound=True),
Process(pid='P5', arrival_time=6, burst_time=2, priority=3,
cpu_bursts=[2], io_bursts=[], is_io_bound=False),
] ]
@ -127,6 +135,14 @@ def main():
help='服务时间范围 (格式: min,max)') help='服务时间范围 (格式: min,max)')
parser.add_argument('--priority', type=str, default='1,10', parser.add_argument('--priority', type=str, default='1,10',
help='优先级范围 (格式: min,max)') help='优先级范围 (格式: min,max)')
parser.add_argument('--io-prob', type=float, default=0.5,
help='进程有IO操作的概率 0.0-1.0 (默认: 0.5)')
parser.add_argument('--io-count', type=str, default='1,4',
help='IO操作次数范围 (格式: min,max, 默认: 1,4)')
parser.add_argument('--io-time', type=str, default='3,15',
help='每次IO时间范围 (格式: min,max, 默认: 3,15)')
parser.add_argument('--io-first', type=float, default=0.0,
help='以IO开始的概率 0.0-1.0 (默认: 0.0, 即全部先CPU)')
args = parser.parse_args() args = parser.parse_args()
@ -144,6 +160,8 @@ def main():
arrival_range = tuple(map(int, args.arrival.split(','))) arrival_range = tuple(map(int, args.arrival.split(',')))
burst_range = tuple(map(int, args.burst.split(','))) burst_range = tuple(map(int, args.burst.split(',')))
priority_range = tuple(map(int, args.priority.split(','))) priority_range = tuple(map(int, args.priority.split(',')))
io_count_range = tuple(map(int, args.io_count.split(',')))
io_time_range = tuple(map(int, args.io_time.split(',')))
seed = args.seed if args.seed != -1 else None seed = args.seed if args.seed != -1 else None
@ -152,7 +170,11 @@ def main():
seed=seed, seed=seed,
arrival_range=arrival_range, arrival_range=arrival_range,
burst_range=burst_range, burst_range=burst_range,
priority_range=priority_range priority_range=priority_range,
io_probability=args.io_prob,
io_count_range=io_count_range,
io_time_range=io_time_range,
io_first_prob=args.io_first
) )
title = f"随机测试数据 (n={args.num}, seed={args.seed if seed else 'None'})" title = f"随机测试数据 (n={args.num}, seed={args.seed if seed else 'None'})"

View File

@ -1,11 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
多级反馈队列调度算法 (MLFQ) 多级反馈队列调度算法 (MLFQ)
Multilevel Feedback Queue 支持 IO 模拟
""" """
from collections import deque
from typing import List, Dict from typing import List, Dict
from collections import deque
import heapq
from base import ( from base import (
Process, Process,
@ -16,83 +17,127 @@ from base import (
class MLFQScheduler(ProcessScheduler): class MLFQScheduler(ProcessScheduler):
"""多级反馈队列调度 (Multilevel Feedback Queue)""" """多级反馈队列调度"""
def __init__(self, processes: List[Process], queues: List[int] = None): def __init__(self, processes: List[Process], num_queues: int = 3, base_time_slice: int = 4):
super().__init__(processes) super().__init__(processes)
# 每层队列的时间片大小 self.num_queues = num_queues
self.queues = queues or [4, 8, 16] self.base_time_slice = base_time_slice
self.aging_time = 50
def get_time_slice(self, queue_idx: int) -> int:
return self.base_time_slice * (2 ** queue_idx)
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""MLFQ 调度算法""" """MLFQ 调度算法 (支持IO模拟)"""
processes = sorted(self.processes, key=lambda p: p.arrival_time) all_processes = list(self.processes)
n = len(all_processes)
for p in all_processes:
self.init_process(p, p.arrival_time)
p.queue_idx = 0
# 事件: (时间, 类型, uid, 进程)
events = []
for p in all_processes:
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
queues = [deque() for _ in range(self.num_queues)]
completed = []
io_waiting = {} # {进程: IO完成时间}
queues = [deque() for _ in self.queues]
current_time = 0 current_time = 0
completed = 0 max_iterations = 10000 # 防止死循环
index = 0 iterations = 0
while completed < len(processes): while len(completed) < n and iterations < max_iterations:
while index < len(processes) and processes[index].arrival_time <= current_time: iterations += 1
queues[0].append(processes[index])
index += 1
# 老化 # 1. 处理到达事件
for i in range(1, len(queues)): while events and events[0][0] <= current_time:
for p in list(queues[i]): _, etype, _, p = heapq.heappop(events)
wait_time = current_time - p.arrival_time - (p.burst_time - p.remaining_time) if etype == 'arrival':
if wait_time > self.aging_time: p.status = self.STATUS_READY
queues[i].remove(p) queues[0].append(p)
queues[max(0, i-1)].append(p) elif etype == 'io_complete':
io_waiting.pop(p.pid, None)
p.status = self.STATUS_READY
queues[p.queue_idx].append(p)
queue_idx = -1 # 2. 检查 IO 完成
for i in range(len(queues)): completed_io = []
for p, io_end_time in io_waiting.items():
if io_end_time <= current_time:
completed_io.append(p)
for p in completed_io:
io_waiting.pop(p.pid, None)
p.status = self.STATUS_READY
queues[p.queue_idx].append(p)
# 3. 找最高优先级非空队列
q_idx = -1
for i in range(self.num_queues):
if queues[i]: if queues[i]:
queue_idx = i q_idx = i
break break
if queue_idx >= 0: if q_idx == -1:
p = queues[queue_idx].popleft() # 所有队列为空,推进时间
next_events = [e[0] for e in events if e[0] > current_time]
next_io = [t for t in io_waiting.values() if t > current_time]
next_times = next_events + next_io
if next_times:
current_time = min(next_times)
continue
# 4. 取进程执行
p = queues[q_idx].popleft()
if p.start_time == -1: if p.start_time == -1:
p.start_time = current_time p.start_time = current_time
p.status = self.STATUS_RUNNING
exec_time = min(self.queues[queue_idx], p.remaining_time) ts = self.get_time_slice(q_idx)
p.remaining_time -= exec_time
current_time += exec_time
while index < len(processes) and processes[index].arrival_time <= current_time: if p.current_cpu_idx < len(p.cpu_bursts):
queues[0].append(processes[index]) cpu_burst = p.cpu_bursts[p.current_cpu_idx]
index += 1 exec_t = min(ts, cpu_burst)
if p.remaining_time > 0: self.gantt_chart.append((current_time, p.pid, 'CPU', exec_t))
if queue_idx < len(queues) - 1:
queues[queue_idx + 1].append(p) current_time += exec_t
else: p.remaining_cpu_time -= exec_t
queues[queue_idx].append(p)
if exec_t >= cpu_burst:
p.current_cpu_idx += 1
io_idx = p.current_cpu_idx - 1
if io_idx < len(p.io_bursts):
io_t = p.io_bursts[io_idx]
p.status = self.STATUS_IO_WAIT
io_waiting[p.pid] = current_time + io_t
heapq.heappush(events, (current_time + io_t, 'io_complete', id(p), p))
else: else:
p.status = self.STATUS_TERMINATED
p.completion_time = current_time
self.calculate_metrics(p, current_time) self.calculate_metrics(p, current_time)
self.results.append(p) completed.append(p)
completed += 1
else: else:
current_time += 1 p.status = self.STATUS_READY
nq = min(q_idx + 1, self.num_queues - 1)
p.queue_idx = nq
queues[nq].append(p)
else:
p.status = self.STATUS_TERMINATED
p.completion_time = current_time
self.calculate_metrics(p, current_time)
completed.append(p)
return self.print_results(f"MLFQ (多级反馈队列, 队列时间片={self.queues})") self.results = completed
return self.print_results("MLFQ (多级反馈队列)")
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
print("\n" + "="*60) scheduler = MLFQScheduler(processes)
print("多级反馈队列调度 (默认配置)") scheduler.schedule()
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()

View File

@ -1,9 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
优先级调度算法 (Priority Scheduling) 优先级调度算法 (Priority)
支持 IO 模拟
""" """
from typing import List, Dict from typing import List, Dict
import heapq
from base import ( from base import (
Process, Process,
@ -14,95 +16,88 @@ from base import (
class PriorityScheduler(ProcessScheduler): class PriorityScheduler(ProcessScheduler):
"""优先级调度""" """优先级调度 (数值越小优先级越高)
支持 IO 模拟
"""
def __init__(self, processes: List[Process], preemptive: bool = False): def __init__(self, processes: List[Process], preemptive: bool = False):
super().__init__(processes) super().__init__(processes)
self.preemptive = preemptive self.preemptive = preemptive
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""优先级调度算法""" """优先级调度算法 (支持IO模拟)"""
if self.preemptive: all_processes = list(self.processes)
return self.schedule_preemptive() for p in all_processes:
return self.schedule_non_preemptive() self.init_process(p, p.arrival_time)
events = []
for p in all_processes:
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
ready_queue = [] # (priority, pid, process)
completed = []
def schedule_non_preemptive(self) -> Dict:
"""非抢占式优先级调度"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0 current_time = 0
completed = 0
while completed < len(processes): while len(completed) < len(all_processes):
for p in processes: while events and events[0][0] <= current_time:
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results: event_time, event_type, uid, p = heapq.heappop(events)
ready_queue.append(p)
if ready_queue: if event_type == 'arrival':
ready_queue.sort(key=lambda p: p.priority) p.status = self.STATUS_READY
p = ready_queue.pop(0) heapq.heappush(ready_queue, (p.priority, id(p), p))
elif event_type == 'io_complete':
if p.status == self.STATUS_IO_WAIT:
p.status = self.STATUS_READY
heapq.heappush(ready_queue, (p.priority, id(p), p))
p.start_time = current_time if not ready_queue:
current_time += p.burst_time if events:
self.calculate_metrics(p, current_time) current_time = events[0][0]
self.results.append(p) continue
completed += 1
else: else:
current_time += 1 break
return self.print_results("优先级调度 (非抢占)") _, _, current_process = heapq.heappop(ready_queue)
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: if current_process.start_time == -1:
current_process.start_time = current_time current_process.start_time = current_time
current_process.remaining_time -= 1 current_process.status = self.STATUS_RUNNING
current_time += 1
if current_process.remaining_time == 0: if current_process.current_cpu_idx < len(current_process.cpu_bursts):
self.calculate_metrics(current_process, current_time) cpu_burst = current_process.cpu_bursts[current_process.current_cpu_idx]
self.results.append(current_process)
completed += 1 self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
current_process = None
current_time += cpu_burst
current_process.remaining_cpu_time -= cpu_burst
current_process.current_cpu_idx += 1
io_idx = current_process.current_cpu_idx - 1
if io_idx < len(current_process.io_bursts):
io_time = current_process.io_bursts[io_idx]
current_process.status = self.STATUS_IO_WAIT
heapq.heappush(events, (current_time + io_time, 'io_complete', id(current_process), current_process))
else: else:
current_time += 1 current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
else:
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
return self.print_results("优先级调度 (抢占)") self.results = completed
return self.print_results("Priority (优先级调度)")
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
print("\n" + "="*60) scheduler = PriorityScheduler(processes)
print("非抢占式优先级调度") scheduler.schedule()
print("="*60)
scheduler1 = PriorityScheduler(processes, preemptive=False)
scheduler1.schedule()
print("\n" + "="*60)
print("抢占式优先级调度")
print("="*60)
scheduler2 = PriorityScheduler(processes, preemptive=True)
scheduler2.schedule()

View File

@ -1,11 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
时间片轮转调度算法 (RR) 时间片轮转调度算法 (RR)
Round Robin 支持 IO 模拟
""" """
from collections import deque
from typing import List, Dict from typing import List, Dict
from collections import deque
import heapq
from base import ( from base import (
Process, Process,
@ -16,58 +17,110 @@ from base import (
class RoundRobinScheduler(ProcessScheduler): class RoundRobinScheduler(ProcessScheduler):
"""时间片轮转调度 (Round Robin)""" """时间片轮转调度"""
def __init__(self, processes: List[Process], time_slice: int = 4): def __init__(self, processes: List[Process], time_slice: int = 4):
super().__init__(processes) super().__init__(processes)
self.time_slice = time_slice self.time_slice = time_slice
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""RR 调度算法""" """RR 调度算法 (支持IO模拟)"""
processes = sorted(self.processes, key=lambda p: p.arrival_time) all_processes = list(self.processes)
n = len(all_processes)
for p in all_processes:
self.init_process(p, p.arrival_time)
events = []
for p in all_processes:
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
ready_queue = deque() ready_queue = deque()
completed = []
io_waiting = {} # {进程PID: IO完成时间}
current_time = 0 current_time = 0
completed = 0 max_iterations = 10000
index = 0 iterations = 0
while completed < len(processes): while len(completed) < n and iterations < max_iterations:
while index < len(processes) and processes[index].arrival_time <= current_time: iterations += 1
ready_queue.append(processes[index])
index += 1
if ready_queue: # 1. 处理到达事件
while events and events[0][0] <= current_time:
_, etype, _, p = heapq.heappop(events)
if etype == 'arrival':
p.status = self.STATUS_READY
ready_queue.append(p)
elif etype == 'io_complete':
io_waiting.pop(p.pid, None)
p.status = self.STATUS_READY
ready_queue.append(p)
# 2. 检查 IO 完成
completed_io = []
for p, io_end_time in io_waiting.items():
if io_end_time <= current_time:
completed_io.append(p)
for p in completed_io:
io_waiting.pop(p.pid, None)
p.status = self.STATUS_READY
ready_queue.append(p)
if not ready_queue:
# 队列为空,推进时间
next_events = [e[0] for e in events if e[0] > current_time]
next_io = [t for t in io_waiting.values() if t > current_time]
next_times = next_events + next_io
if next_times:
current_time = min(next_times)
continue
# 3. 取进程执行
p = ready_queue.popleft() p = ready_queue.popleft()
if p.start_time == -1: if p.start_time == -1:
p.start_time = current_time p.start_time = current_time
p.status = self.STATUS_RUNNING
exec_time = min(self.time_slice, p.remaining_time) if p.current_cpu_idx < len(p.cpu_bursts):
p.remaining_time -= exec_time cpu_burst = p.cpu_bursts[p.current_cpu_idx]
current_time += exec_time exec_t = min(self.time_slice, cpu_burst)
while index < len(processes) and processes[index].arrival_time <= current_time: self.gantt_chart.append((current_time, p.pid, 'CPU', exec_t))
ready_queue.append(processes[index])
index += 1
if p.remaining_time > 0: current_time += exec_t
p.remaining_cpu_time -= exec_t
if exec_t >= cpu_burst:
p.current_cpu_idx += 1
io_idx = p.current_cpu_idx - 1
if io_idx < len(p.io_bursts):
io_t = p.io_bursts[io_idx]
p.status = self.STATUS_IO_WAIT
io_waiting[p.pid] = current_time + io_t
heapq.heappush(events, (current_time + io_t, 'io_complete', id(p), p))
else:
p.status = self.STATUS_TERMINATED
p.completion_time = current_time
self.calculate_metrics(p, current_time)
completed.append(p)
else:
p.status = self.STATUS_READY
ready_queue.append(p) ready_queue.append(p)
else: else:
p.status = self.STATUS_TERMINATED
p.completion_time = current_time
self.calculate_metrics(p, current_time) self.calculate_metrics(p, current_time)
self.results.append(p) completed.append(p)
completed += 1
else:
current_time += 1
return self.print_results(f"RR (时间片轮转, time_slice={self.time_slice})") self.results = completed
return self.print_results(f"RR (时间片轮转, q={self.time_slice})")
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
for ts in [2, 4, 8]: scheduler = RoundRobinScheduler(processes, time_slice=4)
print("\n" + "="*60)
print(f"时间片轮转 (time_slice={ts})")
print("="*60)
scheduler = RoundRobinScheduler(processes, time_slice=ts)
scheduler.schedule() scheduler.schedule()

View File

@ -1,10 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
短作业优先调度算法 (SJF) 最短作业优先调度算法 (SJF/SRTF)
Shortest Job First / Shortest Remaining Time First (SRTF) Shortest Job First / Shortest Remaining Time First
支持 IO 模拟
""" """
from typing import List, Dict from typing import List, Dict
from collections import deque
import heapq
from base import ( from base import (
Process, Process,
@ -15,89 +18,98 @@ from base import (
class SJFScheduler(ProcessScheduler): class SJFScheduler(ProcessScheduler):
"""短作业优先调度 (Shortest Job First)""" """最短作业优先调度 (SJF/SRTF)
SJF: 非抢占式选择剩余时间最短的进程
SRTF: 抢占式选择剩余时间最短的进程
支持 IO 模拟
"""
def __init__(self, processes: List[Process], preemptive: bool = False): def __init__(self, processes: List[Process], preemptive: bool = False):
super().__init__(processes) super().__init__(processes)
self.preemptive = preemptive self.preemptive = preemptive
def schedule(self) -> Dict: def schedule(self) -> Dict:
"""SJF 调度算法""" """SJF/SRTF 调度算法 (支持IO模拟)"""
if self.preemptive: all_processes = list(self.processes)
return self.schedule_preemptive() for p in all_processes:
return self.schedule_non_preemptive() self.init_process(p, p.arrival_time)
# 事件队列: (时间, 事件类型, 唯一ID, 进程)
events = []
for p in all_processes:
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
ready_queue = [] # 就绪队列 (需要排序)
completed = []
def schedule_non_preemptive(self) -> Dict:
"""非抢占式 SJF"""
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0 current_time = 0
completed = 0
while completed < len(processes): while len(completed) < len(all_processes):
for p in processes: # 处理事件
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results: while events and events[0][0] <= current_time:
event_time, event_type, uid, p = heapq.heappop(events)
if event_type == 'arrival':
p.status = self.STATUS_READY
ready_queue.append(p)
elif event_type == 'io_complete':
if p.status == self.STATUS_IO_WAIT:
p.status = self.STATUS_READY
ready_queue.append(p) ready_queue.append(p)
if ready_queue: if not ready_queue:
ready_queue.sort(key=lambda p: p.burst_time) if events:
p = ready_queue.pop(0) current_time = events[0][0]
continue
p.start_time = current_time
current_time += p.burst_time
self.calculate_metrics(p, current_time)
self.results.append(p)
completed += 1
else: else:
current_time += 1 break
return self.print_results("SJF (短作业优先 - 非抢占)") # 按剩余时间排序
ready_queue.sort(key=lambda p: (p.remaining_cpu_time, id(p)))
current_process = ready_queue.pop(0)
def schedule_preemptive(self) -> Dict: if current_process.start_time == -1:
"""抢占式 SJF (SRTF)""" current_process.start_time = current_time
processes = sorted(self.processes, key=lambda p: p.arrival_time)
ready_queue: List[Process] = []
current_time = 0
completed = 0
while completed < len(processes): current_process.status = self.STATUS_RUNNING
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: # 执行 CPU burst
ready_queue.sort(key=lambda p: p.remaining_time) if current_process.current_cpu_idx < len(current_process.cpu_bursts):
p = ready_queue[0] cpu_burst = current_process.cpu_bursts[current_process.current_cpu_idx]
if p.start_time == -1: self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
p.start_time = current_time
p.remaining_time -= 1 current_time += cpu_burst
current_time += 1 current_process.remaining_cpu_time -= cpu_burst
current_process.current_cpu_idx += 1
if p.remaining_time == 0: io_idx = current_process.current_cpu_idx - 1
self.calculate_metrics(p, current_time) if io_idx < len(current_process.io_bursts):
self.results.append(p) io_time = current_process.io_bursts[io_idx]
ready_queue.remove(p) current_process.status = self.STATUS_IO_WAIT
completed += 1 heapq.heappush(events, (current_time + io_time, 'io_complete', id(current_process), current_process))
else: else:
current_time += 1 current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
else:
current_process.status = self.STATUS_TERMINATED
current_process.completion_time = current_time
self.calculate_metrics(current_process, current_time)
completed.append(current_process)
return self.print_results("SRTF (最短剩余时间优先 - 抢占)") self.results = completed
algo_name = "SRTF (最短剩余时间优先)" if self.preemptive else "SJF (最短作业优先)"
return self.print_results(algo_name)
if __name__ == "__main__": if __name__ == "__main__":
processes = generate_random_processes(n=5, seed=42) processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
print_processes(processes, "测试数据") print_processes(processes, "测试数据")
print("\n" + "="*60) print("\n--- SJF (非抢占) ---")
print("非抢占式 SJF") scheduler = SJFScheduler(processes, preemptive=False)
print("="*60) scheduler.schedule()
scheduler1 = SJFScheduler(processes, preemptive=False)
scheduler1.schedule()
print("\n" + "="*60)
print("抢占式 SJF (SRTF)")
print("="*60)
scheduler2 = SJFScheduler(processes, preemptive=True)
scheduler2.schedule()