refactor: 修改实验步骤
This commit is contained in:
parent
56e3cc9bf4
commit
001416e399
|
|
@ -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
|
||||||
从提交到首次运行的时间
|
从提交到首次运行的时间
|
||||||
"""
|
"""
|
||||||
p.completion_time = current_time
|
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.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}")
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
current_time += p.burst_time
|
|
||||||
self.calculate_metrics(p, current_time)
|
|
||||||
self.results.append(p)
|
|
||||||
|
|
||||||
|
while len(completed) < len(all_processes):
|
||||||
|
# 1. 处理所有当前时刻的事件
|
||||||
|
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)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
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 = [] # (response_ratio, pid, process)
|
||||||
|
completed = []
|
||||||
|
|
||||||
current_time = 0
|
current_time = 0
|
||||||
completed = 0
|
|
||||||
|
|
||||||
while completed < len(processes):
|
while len(completed) < len(all_processes):
|
||||||
# 添加所有到达的进程
|
while events and events[0][0] <= current_time:
|
||||||
for p in processes:
|
event_time, event_type, uid, p = heapq.heappop(events)
|
||||||
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: self.calculate_response_ratio(p, current_time),
|
|
||||||
reverse=True # 响应比高优先
|
|
||||||
)
|
|
||||||
p = ready_queue.pop(0)
|
|
||||||
|
|
||||||
p.start_time = current_time
|
if event_type == 'arrival':
|
||||||
current_time += p.burst_time
|
p.status = self.STATUS_READY
|
||||||
self.calculate_metrics(p, current_time)
|
ready_queue.append(p)
|
||||||
self.results.append(p)
|
elif event_type == 'io_complete':
|
||||||
completed += 1
|
if p.status == self.STATUS_IO_WAIT:
|
||||||
|
p.status = self.STATUS_READY
|
||||||
|
ready_queue.append(p)
|
||||||
|
|
||||||
|
if not ready_queue:
|
||||||
|
if events:
|
||||||
|
current_time = events[0][0]
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
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:
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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'})"
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
p.start_time = current_time
|
||||||
|
p.status = self.STATUS_RUNNING
|
||||||
|
|
||||||
|
ts = self.get_time_slice(q_idx)
|
||||||
|
|
||||||
|
if p.current_cpu_idx < len(p.cpu_bursts):
|
||||||
|
cpu_burst = p.cpu_bursts[p.current_cpu_idx]
|
||||||
|
exec_t = min(ts, cpu_burst)
|
||||||
|
|
||||||
if p.start_time == -1:
|
self.gantt_chart.append((current_time, p.pid, 'CPU', exec_t))
|
||||||
p.start_time = current_time
|
|
||||||
|
|
||||||
exec_time = min(self.queues[queue_idx], p.remaining_time)
|
current_time += exec_t
|
||||||
p.remaining_time -= exec_time
|
p.remaining_cpu_time -= exec_t
|
||||||
current_time += exec_time
|
|
||||||
|
|
||||||
while index < len(processes) and processes[index].arrival_time <= current_time:
|
if exec_t >= cpu_burst:
|
||||||
queues[0].append(processes[index])
|
p.current_cpu_idx += 1
|
||||||
index += 1
|
io_idx = p.current_cpu_idx - 1
|
||||||
|
if io_idx < len(p.io_bursts):
|
||||||
if p.remaining_time > 0:
|
io_t = p.io_bursts[io_idx]
|
||||||
if queue_idx < len(queues) - 1:
|
p.status = self.STATUS_IO_WAIT
|
||||||
queues[queue_idx + 1].append(p)
|
io_waiting[p.pid] = current_time + io_t
|
||||||
|
heapq.heappush(events, (current_time + io_t, 'io_complete', id(p), p))
|
||||||
else:
|
else:
|
||||||
queues[queue_idx].append(p)
|
p.status = self.STATUS_TERMINATED
|
||||||
|
p.completion_time = current_time
|
||||||
|
self.calculate_metrics(p, current_time)
|
||||||
|
completed.append(p)
|
||||||
else:
|
else:
|
||||||
self.calculate_metrics(p, current_time)
|
p.status = self.STATUS_READY
|
||||||
self.results.append(p)
|
nq = min(q_idx + 1, self.num_queues - 1)
|
||||||
completed += 1
|
p.queue_idx = nq
|
||||||
|
queues[nq].append(p)
|
||||||
else:
|
else:
|
||||||
current_time += 1
|
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()
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
def schedule_non_preemptive(self) -> Dict:
|
events = []
|
||||||
"""非抢占式优先级调度"""
|
for p in all_processes:
|
||||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
|
||||||
ready_queue: List[Process] = []
|
|
||||||
|
ready_queue = [] # (priority, pid, process)
|
||||||
|
completed = []
|
||||||
|
|
||||||
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 event_type == 'arrival':
|
||||||
|
p.status = self.STATUS_READY
|
||||||
|
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))
|
||||||
|
|
||||||
if ready_queue:
|
if not ready_queue:
|
||||||
ready_queue.sort(key=lambda p: p.priority)
|
if events:
|
||||||
p = ready_queue.pop(0)
|
current_time = events[0][0]
|
||||||
|
continue
|
||||||
p.start_time = current_time
|
else:
|
||||||
current_time += p.burst_time
|
break
|
||||||
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:
|
_, _, current_process = heapq.heappop(ready_queue)
|
||||||
ready_queue.sort(key=lambda p: p.priority)
|
|
||||||
|
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]
|
||||||
|
|
||||||
if current_process is None or current_process.priority > ready_queue[0].priority:
|
self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
|
||||||
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 += cpu_burst
|
||||||
current_time += 1
|
current_process.remaining_cpu_time -= cpu_burst
|
||||||
|
current_process.current_cpu_idx += 1
|
||||||
|
|
||||||
if current_process.remaining_time == 0:
|
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)
|
self.calculate_metrics(current_process, current_time)
|
||||||
self.results.append(current_process)
|
completed.append(current_process)
|
||||||
completed += 1
|
|
||||||
current_process = None
|
|
||||||
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)
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
|
||||||
|
|
@ -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. 处理到达事件
|
||||||
p = ready_queue.popleft()
|
while events and events[0][0] <= current_time:
|
||||||
|
_, etype, _, p = heapq.heappop(events)
|
||||||
if p.start_time == -1:
|
if etype == 'arrival':
|
||||||
p.start_time = current_time
|
p.status = self.STATUS_READY
|
||||||
|
|
||||||
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)
|
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()
|
||||||
|
|
||||||
|
if p.start_time == -1:
|
||||||
|
p.start_time = current_time
|
||||||
|
p.status = self.STATUS_RUNNING
|
||||||
|
|
||||||
|
if p.current_cpu_idx < len(p.cpu_bursts):
|
||||||
|
cpu_burst = p.cpu_bursts[p.current_cpu_idx]
|
||||||
|
exec_t = min(self.time_slice, cpu_burst)
|
||||||
|
|
||||||
|
self.gantt_chart.append((current_time, p.pid, 'CPU', exec_t))
|
||||||
|
|
||||||
|
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:
|
else:
|
||||||
self.calculate_metrics(p, current_time)
|
p.status = self.STATUS_READY
|
||||||
self.results.append(p)
|
ready_queue.append(p)
|
||||||
completed += 1
|
|
||||||
else:
|
else:
|
||||||
current_time += 1
|
p.status = self.STATUS_TERMINATED
|
||||||
|
p.completion_time = current_time
|
||||||
|
self.calculate_metrics(p, current_time)
|
||||||
|
completed.append(p)
|
||||||
|
|
||||||
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)
|
scheduler.schedule()
|
||||||
print(f"时间片轮转 (time_slice={ts})")
|
|
||||||
print("="*60)
|
|
||||||
scheduler = RoundRobinScheduler(processes, time_slice=ts)
|
|
||||||
scheduler.schedule()
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
def schedule_non_preemptive(self) -> Dict:
|
# 事件队列: (时间, 事件类型, 唯一ID, 进程)
|
||||||
"""非抢占式 SJF"""
|
events = []
|
||||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
for p in all_processes:
|
||||||
ready_queue: List[Process] = []
|
heapq.heappush(events, (p.arrival_time, 'arrival', id(p), p))
|
||||||
|
|
||||||
|
ready_queue = [] # 就绪队列 (需要排序)
|
||||||
|
completed = []
|
||||||
|
|
||||||
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)
|
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)
|
||||||
|
|
||||||
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
|
else:
|
||||||
current_time += p.burst_time
|
break
|
||||||
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)
|
ready_queue.sort(key=lambda p: (p.remaining_cpu_time, id(p)))
|
||||||
p = ready_queue[0]
|
current_process = ready_queue.pop(0)
|
||||||
|
|
||||||
|
if current_process.start_time == -1:
|
||||||
|
current_process.start_time = current_time
|
||||||
|
|
||||||
|
current_process.status = self.STATUS_RUNNING
|
||||||
|
|
||||||
|
# 执行 CPU burst
|
||||||
|
if current_process.current_cpu_idx < len(current_process.cpu_bursts):
|
||||||
|
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:
|
||||||
|
current_process.status = self.STATUS_TERMINATED
|
||||||
|
current_process.completion_time = current_time
|
||||||
|
self.calculate_metrics(current_process, current_time)
|
||||||
|
completed.append(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)
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue