refactor: 修改实验步骤
This commit is contained in:
parent
56e3cc9bf4
commit
001416e399
|
|
@ -10,11 +10,32 @@ from typing import List, Dict, Optional
|
|||
|
||||
@dataclass
|
||||
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
|
||||
arrival_time: int = 0
|
||||
burst_time: int = 0
|
||||
burst_time: int = 0 # 总CPU时间 = sum(cpu_bursts)
|
||||
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)
|
||||
start_time: int = -1
|
||||
completion_time: int = 0
|
||||
|
|
@ -22,9 +43,28 @@ class Process:
|
|||
turnaround_time: int = 0
|
||||
weighted_turnaround_time: float = 0.0 # 带权周转时间 = 周转时间/服务时间
|
||||
response_time: int = 0
|
||||
io_blocked_time: int = 0 # 因等待IO而阻塞的时间
|
||||
|
||||
def __post_init__(self):
|
||||
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):
|
||||
"""重置进程状态"""
|
||||
|
|
@ -35,18 +75,92 @@ class Process:
|
|||
self.turnaround_time = 0
|
||||
self.weighted_turnaround_time = 0.0
|
||||
self.response_time = 0
|
||||
self.io_blocked_time = 0
|
||||
|
||||
|
||||
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]):
|
||||
self.processes = [p for p in processes]
|
||||
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):
|
||||
"""
|
||||
计算进程性能指标
|
||||
计算进程性能指标 (支持IO模拟)
|
||||
|
||||
周转时间 (Turnaround Time): CT - AT
|
||||
进程从提交到完成的总时间
|
||||
|
|
@ -57,57 +171,98 @@ class ProcessScheduler:
|
|||
|
||||
等待时间 (Waiting Time): TAT - BT
|
||||
进程在就绪队列中等待的时间总和
|
||||
注意: 这里只计算CPU等待时间,不包括IO等待时间
|
||||
|
||||
响应时间 (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.turnaround_time = p.completion_time - p.arrival_time
|
||||
p.waiting_time = p.turnaround_time - p.burst_time
|
||||
p.response_time = p.start_time - p.arrival_time
|
||||
# 等待时间 = 周转时间 - 总CPU时间 - IO等待时间
|
||||
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.io_wait = p.io_wait_time
|
||||
|
||||
def print_results(self, algorithm_name: str) -> Dict:
|
||||
"""打印调度结果"""
|
||||
"""打印调度结果 (支持IO模拟)"""
|
||||
n = len(self.results)
|
||||
if n == 0:
|
||||
return {}
|
||||
|
||||
avg_waiting = sum(p.waiting_time for p in self.results) / n
|
||||
avg_turnaround = sum(p.turnaround_time for p in self.results) / n
|
||||
avg_weighted_turnaround = sum(p.weighted_turnaround_time for p in self.results) / n
|
||||
avg_response = sum(p.response_time for p in self.results) / n
|
||||
|
||||
print(f"\n{'='*70}")
|
||||
# 计算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"{'='*70}")
|
||||
print(f"{'PID':<6}{'到达':<6}{'服务':<6}{'开始':<6}{'完成':<6}"
|
||||
f"{'等待':<6}{'周转':<6}{'带权周转':<10}{'响应':<6}")
|
||||
print("-" * 70)
|
||||
print(f"{'='*85}")
|
||||
print(f"{'PID':<6}{'类型':<6}{'起始':<6}{'到达':<6}{'服务':<6}{'IO次数':<6}{'IO时间':<8}"
|
||||
f"{'周转':<6}{'CPU等待':<8}{'IO等待':<8}{'响应':<6}")
|
||||
print("-" * 85)
|
||||
|
||||
for p in self.results:
|
||||
print(f"{p.pid:<6}{p.arrival_time:<6}{p.burst_time:<6}"
|
||||
f"{p.start_time:<6}{p.completion_time:<6}"
|
||||
f"{p.waiting_time:<6}{p.turnaround_time:<6}"
|
||||
f"{p.weighted_turnaround_time:<10.2f}"
|
||||
f"{p.response_time:<6}")
|
||||
proc_type = "IO" if p.is_io_bound else "CPU"
|
||||
start_phase = "IO" if p.starts_with_io else "CPU"
|
||||
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}{p.total_io_time:<8}"
|
||||
f"{p.turnaround_time:<6}{p.waiting_time:<8}{p.io_wait:<8}{p.response_time:<6}")
|
||||
|
||||
print("-" * 70)
|
||||
print(f"{'平均等待时间:':<18} {avg_waiting:.2f}")
|
||||
print(f"{'平均周转时间:':<18} {avg_turnaround:.2f}")
|
||||
print(f"{'平均带权周转时间:':<18} {avg_weighted_turnaround:.2f}")
|
||||
print(f"{'平均响应时间:':<18} {avg_response:.2f}")
|
||||
print("-" * 85)
|
||||
print(f"{'平均等待时间:':<22} {avg_waiting:.2f}")
|
||||
print(f"{'平均周转时间:':<22} {avg_turnaround:.2f}")
|
||||
print(f"{'平均带权周转时间:':<22} {avg_weighted_turnaround:.2f}")
|
||||
print(f"{'平均响应时间:':<22} {avg_response:.2f}")
|
||||
|
||||
# CPU 利用率
|
||||
total_burst = sum(p.burst_time for p in self.results)
|
||||
# CPU 利用率计算 (考虑IO模拟)
|
||||
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
|
||||
utilization = (total_burst / total_time) * 100 if total_time > 0 else 0
|
||||
print(f"{'CPU 利用率:':<18} {utilization:.2f}%")
|
||||
# CPU利用率 = CPU执行时间 / 总时间
|
||||
# 注意: 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 {
|
||||
'avg_waiting': avg_waiting,
|
||||
'avg_turnaround': avg_turnaround,
|
||||
'avg_weighted_turnaround': avg_weighted_turnaround,
|
||||
'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,
|
||||
arrival_range: tuple = (0, 50),
|
||||
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]:
|
||||
"""
|
||||
随机生成测试进程集
|
||||
随机生成测试进程集 (支持IO模拟)
|
||||
|
||||
Args:
|
||||
n: 进程数量
|
||||
|
|
@ -127,20 +286,95 @@ def generate_random_processes(
|
|||
arrival_range: 到达时间范围 (min, max)
|
||||
burst_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:
|
||||
进程列表
|
||||
|
||||
示例:
|
||||
# 生成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:
|
||||
random.seed(seed)
|
||||
|
||||
processes = []
|
||||
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(
|
||||
pid=f'P{i+1}',
|
||||
arrival_time=random.randint(*arrival_range),
|
||||
burst_time=random.randint(*burst_range),
|
||||
priority=random.randint(*priority_range)
|
||||
arrival_time=arrival,
|
||||
burst_time=total_burst,
|
||||
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)
|
||||
|
||||
|
|
@ -150,24 +384,64 @@ def generate_random_processes(
|
|||
|
||||
|
||||
def print_processes(processes: List[Process], title: str = "测试数据"):
|
||||
"""打印进程信息"""
|
||||
print(f"\n{'='*60}")
|
||||
"""打印进程信息 (包含IO模拟信息)"""
|
||||
print(f"\n{'='*80}")
|
||||
print(f"{title}")
|
||||
print(f"{'='*60}")
|
||||
print(f"{'PID':<8}{'到达时间':<10}{'服务时间':<10}{'优先级':<10}")
|
||||
print("-" * 60)
|
||||
print(f"{'='*80}")
|
||||
print(f"{'PID':<6}{'类型':<6}{'起始':<6}{'到达':<6}{'服务':<6}{'IO次数':<6}{'IO时间':<8}{'优先级':<6}")
|
||||
print("-" * 80)
|
||||
|
||||
io_bound_count = 0
|
||||
io_first_count = 0
|
||||
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]):
|
||||
"""打印算法比较结果"""
|
||||
print("\n" + "="*90)
|
||||
"""打印算法比较结果 (包含IO指标)"""
|
||||
print("\n" + "="*100)
|
||||
print("算法性能比较")
|
||||
print("="*90)
|
||||
print(f"{'算法':<10}{'平均等待':<12}{'平均周转':<12}{'平均带权周转':<14}{'平均响应':<12}{'CPU利用率':<12}")
|
||||
print("-" * 90)
|
||||
print("="*100)
|
||||
print(f"{'算法':<8}{'平均等待':<10}{'平均周转':<10}{'平均带权周转':<12}{'平均响应':<10}{'CPU利用率':<10}{'IO阻塞':<10}")
|
||||
print("-" * 100)
|
||||
for name, metrics in results.items():
|
||||
print(f"{name:<10}{metrics['avg_waiting']:<12.2f}{metrics['avg_turnaround']:<12.2f}"
|
||||
f"{metrics.get('avg_weighted_turnaround', 0):<14.2f}"
|
||||
f"{metrics['avg_response']:<12.2f}{metrics['cpu_utilization']:<12.2f}%")
|
||||
print(f"{name:<8}{metrics['avg_waiting']:<10.2f}{metrics['avg_turnaround']:<10.2f}"
|
||||
f"{metrics.get('avg_weighted_turnaround', 0):<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)
|
||||
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 (
|
||||
Process,
|
||||
|
|
@ -15,28 +18,97 @@ from base import (
|
|||
|
||||
|
||||
class FCFSScheduler(ProcessScheduler):
|
||||
"""先来先服务调度 (First Come First Served)"""
|
||||
"""先来先服务调度 (First Come First Served)
|
||||
|
||||
支持 IO 模拟:
|
||||
- 进程执行一个 CPU burst 后进入 IO 等待
|
||||
- IO 等待期间 CPU 可以调度其他就绪进程
|
||||
- IO 完成时进程回到就绪队列
|
||||
"""
|
||||
|
||||
def schedule(self) -> Dict:
|
||||
"""FCFS 调度算法"""
|
||||
# 按到达时间排序
|
||||
ready_queue = sorted(self.processes, key=lambda p: (p.arrival_time, p.pid))
|
||||
"""FCFS 调度算法 (支持IO模拟)"""
|
||||
all_processes = list(self.processes)
|
||||
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
|
||||
for p in ready_queue:
|
||||
if p.arrival_time > current_time:
|
||||
current_time = p.arrival_time
|
||||
last_processed_time = 0
|
||||
|
||||
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 (先来先服务)")
|
||||
|
||||
|
||||
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, "测试数据")
|
||||
|
||||
scheduler = FCFSScheduler(processes)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
高响应比优先调度算法 (HRRN)
|
||||
Highest Response Ratio Next
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
from typing import List, Dict
|
||||
import heapq
|
||||
|
||||
from base import (
|
||||
Process,
|
||||
|
|
@ -15,57 +16,95 @@ from base import (
|
|||
|
||||
|
||||
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:
|
||||
"""HRRN 调度算法"""
|
||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
||||
ready_queue: List[Process] = []
|
||||
current_time = 0
|
||||
completed = 0
|
||||
"""HRRN 调度算法 (支持IO模拟)"""
|
||||
all_processes = list(self.processes)
|
||||
for p in all_processes:
|
||||
self.init_process(p, p.arrival_time)
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
current_time += p.burst_time
|
||||
self.calculate_metrics(p, current_time)
|
||||
self.results.append(p)
|
||||
completed += 1
|
||||
if not ready_queue:
|
||||
if events:
|
||||
current_time = events[0][0]
|
||||
continue
|
||||
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 (高响应比优先)")
|
||||
|
||||
|
||||
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, "测试数据")
|
||||
|
||||
scheduler = HRRNScheduler(processes)
|
||||
|
|
|
|||
|
|
@ -32,13 +32,21 @@ from mlfq import MLFQScheduler
|
|||
from hrrn import HRRNScheduler
|
||||
|
||||
|
||||
# 预设演示数据
|
||||
# 预设演示数据 (包含IO模拟)
|
||||
DEMO_PROCESSES = [
|
||||
Process(pid='P1', arrival_time=0, burst_time=7, priority=3),
|
||||
Process(pid='P2', arrival_time=2, burst_time=4, priority=1),
|
||||
Process(pid='P3', arrival_time=4, burst_time=1, priority=4),
|
||||
Process(pid='P4', arrival_time=5, burst_time=4, priority=2),
|
||||
Process(pid='P5', arrival_time=6, burst_time=2, priority=3),
|
||||
# CPU密集型进程
|
||||
Process(pid='P1', arrival_time=0, burst_time=7, priority=3,
|
||||
cpu_bursts=[7], io_bursts=[], is_io_bound=False),
|
||||
# IO密集型进程: CPU -> IO -> CPU -> IO -> CPU
|
||||
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)')
|
||||
parser.add_argument('--priority', type=str, default='1,10',
|
||||
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()
|
||||
|
||||
|
|
@ -144,6 +160,8 @@ def main():
|
|||
arrival_range = tuple(map(int, args.arrival.split(',')))
|
||||
burst_range = tuple(map(int, args.burst.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
|
||||
|
||||
|
|
@ -152,7 +170,11 @@ def main():
|
|||
seed=seed,
|
||||
arrival_range=arrival_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'})"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
多级反馈队列调度算法 (MLFQ)
|
||||
Multilevel Feedback Queue
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
from collections import deque
|
||||
from typing import List, Dict
|
||||
from collections import deque
|
||||
import heapq
|
||||
|
||||
from base import (
|
||||
Process,
|
||||
|
|
@ -16,83 +17,127 @@ from base import (
|
|||
|
||||
|
||||
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)
|
||||
# 每层队列的时间片大小
|
||||
self.queues = queues or [4, 8, 16]
|
||||
self.aging_time = 50
|
||||
self.num_queues = num_queues
|
||||
self.base_time_slice = base_time_slice
|
||||
|
||||
def get_time_slice(self, queue_idx: int) -> int:
|
||||
return self.base_time_slice * (2 ** queue_idx)
|
||||
|
||||
def schedule(self) -> Dict:
|
||||
"""MLFQ 调度算法"""
|
||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
||||
"""MLFQ 调度算法 (支持IO模拟)"""
|
||||
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
|
||||
completed = 0
|
||||
index = 0
|
||||
max_iterations = 10000 # 防止死循环
|
||||
iterations = 0
|
||||
|
||||
while completed < len(processes):
|
||||
while index < len(processes) and processes[index].arrival_time <= current_time:
|
||||
queues[0].append(processes[index])
|
||||
index += 1
|
||||
while len(completed) < n and iterations < max_iterations:
|
||||
iterations += 1
|
||||
|
||||
# 老化
|
||||
for i in range(1, len(queues)):
|
||||
for p in list(queues[i]):
|
||||
wait_time = current_time - p.arrival_time - (p.burst_time - p.remaining_time)
|
||||
if wait_time > self.aging_time:
|
||||
queues[i].remove(p)
|
||||
queues[max(0, i-1)].append(p)
|
||||
# 1. 处理到达事件
|
||||
while events and events[0][0] <= current_time:
|
||||
_, etype, _, p = heapq.heappop(events)
|
||||
if etype == 'arrival':
|
||||
p.status = self.STATUS_READY
|
||||
queues[0].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
|
||||
for i in range(len(queues)):
|
||||
# 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
|
||||
queues[p.queue_idx].append(p)
|
||||
|
||||
# 3. 找最高优先级非空队列
|
||||
q_idx = -1
|
||||
for i in range(self.num_queues):
|
||||
if queues[i]:
|
||||
queue_idx = i
|
||||
q_idx = i
|
||||
break
|
||||
|
||||
if queue_idx >= 0:
|
||||
p = queues[queue_idx].popleft()
|
||||
if q_idx == -1:
|
||||
# 所有队列为空,推进时间
|
||||
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
|
||||
|
||||
exec_time = min(self.queues[queue_idx], p.remaining_time)
|
||||
p.remaining_time -= exec_time
|
||||
current_time += exec_time
|
||||
ts = self.get_time_slice(q_idx)
|
||||
|
||||
while index < len(processes) and processes[index].arrival_time <= current_time:
|
||||
queues[0].append(processes[index])
|
||||
index += 1
|
||||
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.remaining_time > 0:
|
||||
if queue_idx < len(queues) - 1:
|
||||
queues[queue_idx + 1].append(p)
|
||||
else:
|
||||
queues[queue_idx].append(p)
|
||||
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)
|
||||
self.results.append(p)
|
||||
completed += 1
|
||||
completed.append(p)
|
||||
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__":
|
||||
processes = generate_random_processes(n=5, seed=42)
|
||||
processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
|
||||
print_processes(processes, "测试数据")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("多级反馈队列调度 (默认配置)")
|
||||
print("="*60)
|
||||
scheduler1 = MLFQScheduler(processes)
|
||||
scheduler1.schedule()
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("多级反馈队列调度 (自定义配置 [2, 5, 10])")
|
||||
print("="*60)
|
||||
scheduler2 = MLFQScheduler(processes, queues=[2, 5, 10])
|
||||
scheduler2.schedule()
|
||||
scheduler = MLFQScheduler(processes)
|
||||
scheduler.schedule()
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
优先级调度算法 (Priority Scheduling)
|
||||
优先级调度算法 (Priority)
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
from typing import List, Dict
|
||||
import heapq
|
||||
|
||||
from base import (
|
||||
Process,
|
||||
|
|
@ -14,95 +16,88 @@ from base import (
|
|||
|
||||
|
||||
class PriorityScheduler(ProcessScheduler):
|
||||
"""优先级调度"""
|
||||
"""优先级调度 (数值越小优先级越高)
|
||||
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
def __init__(self, processes: List[Process], preemptive: bool = False):
|
||||
super().__init__(processes)
|
||||
self.preemptive = preemptive
|
||||
|
||||
def schedule(self) -> Dict:
|
||||
"""优先级调度算法"""
|
||||
if self.preemptive:
|
||||
return self.schedule_preemptive()
|
||||
return self.schedule_non_preemptive()
|
||||
"""优先级调度算法 (支持IO模拟)"""
|
||||
all_processes = list(self.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 = [] # (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
|
||||
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)
|
||||
while len(completed) < len(all_processes):
|
||||
while events and events[0][0] <= current_time:
|
||||
event_time, event_type, uid, p = heapq.heappop(events)
|
||||
|
||||
if ready_queue:
|
||||
ready_queue.sort(key=lambda p: p.priority)
|
||||
p = ready_queue.pop(0)
|
||||
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))
|
||||
|
||||
p.start_time = current_time
|
||||
current_time += p.burst_time
|
||||
self.calculate_metrics(p, current_time)
|
||||
self.results.append(p)
|
||||
completed += 1
|
||||
if not ready_queue:
|
||||
if events:
|
||||
current_time = events[0][0]
|
||||
continue
|
||||
else:
|
||||
current_time += 1
|
||||
break
|
||||
|
||||
return self.print_results("优先级调度 (非抢占)")
|
||||
|
||||
def schedule_preemptive(self) -> Dict:
|
||||
"""抢占式优先级调度"""
|
||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
||||
ready_queue: List[Process] = []
|
||||
current_time = 0
|
||||
completed = 0
|
||||
current_process = None
|
||||
|
||||
while completed < len(processes):
|
||||
for p in processes:
|
||||
if p.arrival_time <= current_time and p not in ready_queue and p not in self.results:
|
||||
ready_queue.append(p)
|
||||
|
||||
if ready_queue:
|
||||
ready_queue.sort(key=lambda p: p.priority)
|
||||
|
||||
if current_process is None or current_process.priority > ready_queue[0].priority:
|
||||
if current_process and current_process.remaining_time > 0:
|
||||
ready_queue.append(current_process)
|
||||
|
||||
current_process = ready_queue.pop(0)
|
||||
_, _, current_process = heapq.heappop(ready_queue)
|
||||
|
||||
if current_process.start_time == -1:
|
||||
current_process.start_time = current_time
|
||||
|
||||
current_process.remaining_time -= 1
|
||||
current_time += 1
|
||||
current_process.status = self.STATUS_RUNNING
|
||||
|
||||
if current_process.remaining_time == 0:
|
||||
self.calculate_metrics(current_process, current_time)
|
||||
self.results.append(current_process)
|
||||
completed += 1
|
||||
current_process = None
|
||||
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_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__":
|
||||
processes = generate_random_processes(n=5, seed=42)
|
||||
processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
|
||||
print_processes(processes, "测试数据")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("非抢占式优先级调度")
|
||||
print("="*60)
|
||||
scheduler1 = PriorityScheduler(processes, preemptive=False)
|
||||
scheduler1.schedule()
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("抢占式优先级调度")
|
||||
print("="*60)
|
||||
scheduler2 = PriorityScheduler(processes, preemptive=True)
|
||||
scheduler2.schedule()
|
||||
scheduler = PriorityScheduler(processes)
|
||||
scheduler.schedule()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
时间片轮转调度算法 (RR)
|
||||
Round Robin
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
from collections import deque
|
||||
from typing import List, Dict
|
||||
from collections import deque
|
||||
import heapq
|
||||
|
||||
from base import (
|
||||
Process,
|
||||
|
|
@ -16,58 +17,110 @@ from base import (
|
|||
|
||||
|
||||
class RoundRobinScheduler(ProcessScheduler):
|
||||
"""时间片轮转调度 (Round Robin)"""
|
||||
"""时间片轮转调度"""
|
||||
|
||||
def __init__(self, processes: List[Process], time_slice: int = 4):
|
||||
super().__init__(processes)
|
||||
self.time_slice = time_slice
|
||||
|
||||
def schedule(self) -> Dict:
|
||||
"""RR 调度算法"""
|
||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
||||
"""RR 调度算法 (支持IO模拟)"""
|
||||
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()
|
||||
completed = []
|
||||
io_waiting = {} # {进程PID: IO完成时间}
|
||||
|
||||
current_time = 0
|
||||
completed = 0
|
||||
index = 0
|
||||
max_iterations = 10000
|
||||
iterations = 0
|
||||
|
||||
while completed < len(processes):
|
||||
while index < len(processes) and processes[index].arrival_time <= current_time:
|
||||
ready_queue.append(processes[index])
|
||||
index += 1
|
||||
while len(completed) < n and iterations < max_iterations:
|
||||
iterations += 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()
|
||||
|
||||
if p.start_time == -1:
|
||||
p.start_time = current_time
|
||||
p.status = self.STATUS_RUNNING
|
||||
|
||||
exec_time = min(self.time_slice, p.remaining_time)
|
||||
p.remaining_time -= exec_time
|
||||
current_time += exec_time
|
||||
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)
|
||||
|
||||
while index < len(processes) and processes[index].arrival_time <= current_time:
|
||||
ready_queue.append(processes[index])
|
||||
index += 1
|
||||
self.gantt_chart.append((current_time, p.pid, 'CPU', exec_t))
|
||||
|
||||
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)
|
||||
else:
|
||||
p.status = self.STATUS_TERMINATED
|
||||
p.completion_time = current_time
|
||||
self.calculate_metrics(p, current_time)
|
||||
self.results.append(p)
|
||||
completed += 1
|
||||
else:
|
||||
current_time += 1
|
||||
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__":
|
||||
processes = generate_random_processes(n=5, seed=42)
|
||||
processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
|
||||
print_processes(processes, "测试数据")
|
||||
|
||||
for ts in [2, 4, 8]:
|
||||
print("\n" + "="*60)
|
||||
print(f"时间片轮转 (time_slice={ts})")
|
||||
print("="*60)
|
||||
scheduler = RoundRobinScheduler(processes, time_slice=ts)
|
||||
scheduler = RoundRobinScheduler(processes, time_slice=4)
|
||||
scheduler.schedule()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
短作业优先调度算法 (SJF)
|
||||
Shortest Job First / Shortest Remaining Time First (SRTF)
|
||||
最短作业优先调度算法 (SJF/SRTF)
|
||||
Shortest Job First / Shortest Remaining Time First
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
from typing import List, Dict
|
||||
from collections import deque
|
||||
import heapq
|
||||
|
||||
from base import (
|
||||
Process,
|
||||
|
|
@ -15,89 +18,98 @@ from base import (
|
|||
|
||||
|
||||
class SJFScheduler(ProcessScheduler):
|
||||
"""短作业优先调度 (Shortest Job First)"""
|
||||
"""最短作业优先调度 (SJF/SRTF)
|
||||
|
||||
SJF: 非抢占式,选择剩余时间最短的进程
|
||||
SRTF: 抢占式,选择剩余时间最短的进程
|
||||
|
||||
支持 IO 模拟
|
||||
"""
|
||||
|
||||
def __init__(self, processes: List[Process], preemptive: bool = False):
|
||||
super().__init__(processes)
|
||||
self.preemptive = preemptive
|
||||
|
||||
def schedule(self) -> Dict:
|
||||
"""SJF 调度算法"""
|
||||
if self.preemptive:
|
||||
return self.schedule_preemptive()
|
||||
return self.schedule_non_preemptive()
|
||||
"""SJF/SRTF 调度算法 (支持IO模拟)"""
|
||||
all_processes = list(self.processes)
|
||||
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 = [] # 就绪队列 (需要排序)
|
||||
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
|
||||
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:
|
||||
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)
|
||||
|
||||
if ready_queue:
|
||||
ready_queue.sort(key=lambda p: p.burst_time)
|
||||
p = ready_queue.pop(0)
|
||||
|
||||
p.start_time = current_time
|
||||
current_time += p.burst_time
|
||||
self.calculate_metrics(p, current_time)
|
||||
self.results.append(p)
|
||||
completed += 1
|
||||
if not ready_queue:
|
||||
if events:
|
||||
current_time = events[0][0]
|
||||
continue
|
||||
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:
|
||||
"""抢占式 SJF (SRTF)"""
|
||||
processes = sorted(self.processes, key=lambda p: p.arrival_time)
|
||||
ready_queue: List[Process] = []
|
||||
current_time = 0
|
||||
completed = 0
|
||||
if current_process.start_time == -1:
|
||||
current_process.start_time = current_time
|
||||
|
||||
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)
|
||||
current_process.status = self.STATUS_RUNNING
|
||||
|
||||
if ready_queue:
|
||||
ready_queue.sort(key=lambda p: p.remaining_time)
|
||||
p = ready_queue[0]
|
||||
# 执行 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:
|
||||
p.start_time = current_time
|
||||
self.gantt_chart.append((current_time, current_process.pid, 'CPU', cpu_burst))
|
||||
|
||||
p.remaining_time -= 1
|
||||
current_time += 1
|
||||
current_time += cpu_burst
|
||||
current_process.remaining_cpu_time -= cpu_burst
|
||||
current_process.current_cpu_idx += 1
|
||||
|
||||
if p.remaining_time == 0:
|
||||
self.calculate_metrics(p, current_time)
|
||||
self.results.append(p)
|
||||
ready_queue.remove(p)
|
||||
completed += 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_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__":
|
||||
processes = generate_random_processes(n=5, seed=42)
|
||||
processes = generate_random_processes(n=5, seed=42, io_probability=0.5)
|
||||
print_processes(processes, "测试数据")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("非抢占式 SJF")
|
||||
print("="*60)
|
||||
scheduler1 = SJFScheduler(processes, preemptive=False)
|
||||
scheduler1.schedule()
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("抢占式 SJF (SRTF)")
|
||||
print("="*60)
|
||||
scheduler2 = SJFScheduler(processes, preemptive=True)
|
||||
scheduler2.schedule()
|
||||
print("\n--- SJF (非抢占) ---")
|
||||
scheduler = SJFScheduler(processes, preemptive=False)
|
||||
scheduler.schedule()
|
||||
|
|
|
|||
Loading…
Reference in New Issue