import random
from collections import deque
import json
class PCB:
def __init__(self, pid, arrive, cpu_total, io_gap):
self.pid = pid # 进程标识符
self.arrive = arrive # 到达时间(ms)
self.cpu_need = cpu_total # 剩余CPU执行时间(ms)
self.cpu_total = cpu_total # 总CPU需求(ms)
self.io_gap = io_gap # I/O阻塞间隔(ms)
self.cpu_since_io = 0 # 距上次I/O已执行时间(ms)
self.state = 'NEW' # 进程状态(NEW/READY/RUN/BLOCK/DONE)
self.queue_level = 0 # 所在队列级别(0/1/2)
self.time_slice_remaining = 0 # 当前队列剩余时间片
self.block_end_time = 0 # 阻塞结束时间
self.start_time = -1 # 首次运行时间
self.finish_time = -1 # 完成时间
self.wait_time = 0 # 总等待时间
self.saved_time_slice = 0 # 保存进入阻塞时的剩余时间片
# 队列配置(完全按照任务书要求)
QUEUE_CONFIG = {
0: {'time_slice': 2, 'scheduler': 'RR'}, # Q0: 时间片2ms,RR调度
1: {'time_slice': 4, 'scheduler': 'RR'}, # Q1: 时间片4ms,RR调度
2: {'time_slice': float('inf'), 'scheduler': 'FCFS'} # Q2: 无限时间片,FCFS调度
}
def generate_processes(n=20):
"""随机生成n个进程(完全按照任务书要求)"""
processes = []
for i in range(1, n + 1):
arrive = random.randint(0, 100) # 到达时间范围0-100ms
cpu_total = random.randint(5, 50) # CPU总需求5-50ms
io_gap = random.randint(5, 20) # I/O间隔5-20ms
processes.append(PCB(i, arrive, cpu_total, io_gap))
return processes
def load_processes_from_json(file_path):
"""从JSON文件加载进程数据(符合任务书输入样例格式)"""
try:
with open(file_path, 'r') as f:
data = json.load(f)
processes = []
for item in data:
pid = item['pid']
arrive = item['arrive']
cpu_total = item['cpu_total']
io_gap = item.get('io_gap', random.randint(5, 20))
processes.append(PCB(pid, arrive, cpu_total, io_gap))
return processes
except FileNotFoundError:
print(f"错误:文件 {file_path} 未找到。")
return []
except json.JSONDecodeError:
print(f"错误:文件 {file_path} 不是有效的JSON文件。")
return []
def simulate_scheduling(processes, max_time=10000):
"""模拟多级反馈队列调度过程(优化内存使用和调度逻辑)"""
# 初始化系统状态
ready_queues = [deque() for _ in range(3)] # 三级就绪队列
block_queue = deque() # 阻塞队列
completed_processes = [] # 完成的进程
current_process = None # 当前运行进程
system_time = 0 # 系统时间(ms)
cpu_busy_time = 0 # CPU忙时间(ms)
# 优化:直接生成甘特图段,不保存所有时间点的数据
gantt_segments = []
current_segment = None # 当前甘特图段:(start_time, pid, is_block)
# 等待到达的进程
waiting_processes = sorted(processes, key=lambda p: p.arrive)
total_processes = len(processes)
# 打印初始信息
print(f"开始模拟调度...总进程数: {total_processes}")
while len(completed_processes) < total_processes and system_time < max_time:
# 每1000ms输出一次进度
if system_time % 1000 == 0:
print(f"系统时间: {system_time}ms, 已完成进程: {len(completed_processes)}/{total_processes}")
# 1. 检查新到达的进程
while waiting_processes and waiting_processes[0].arrive <= system_time:
p = waiting_processes.pop(0)
p.state = 'READY'
p.queue_level = 0
p.time_slice_remaining = QUEUE_CONFIG[0]['time_slice']
p.cpu_since_io = 0 # 关键:新到达时清零I/O计数器
ready_queues[0].append(p)
print(f"时间 {system_time}: PID{p.pid} 到达,加入Q0")
# 2. 检查阻塞进程是否到期
while block_queue and block_queue[0].block_end_time <= system_time:
p = block_queue.popleft()
p.state = 'READY'
p.cpu_since_io = 0 # 关键:刚恢复时清零I/O计数器
p.time_slice_remaining = p.saved_time_slice # 恢复剩余时间片
ready_queues[p.queue_level].append(p)
print(f"时间 {system_time}: PID{p.pid} 结束阻塞,加入Q{p.queue_level}")
# 3. 调度进程(CPU空闲时从高优先级队列获取)
if not current_process:
for i in range(3):
if ready_queues[i]:
current_process = ready_queues[i].popleft()
current_process.state = 'RUN'
if current_process.start_time == -1:
current_process.start_time = system_time
if current_process.time_slice_remaining == 0: # 如果剩余时间片为0,重置
current_process.time_slice_remaining = QUEUE_CONFIG[current_process.queue_level]['time_slice']
print(f"时间 {system_time}: PID{current_process.pid} 开始在Q{current_process.queue_level}运行")
break
# 更新甘特图段
current_pid = current_process.pid if current_process else None
is_block = False
if current_process:
current_process.cpu_need -= 1
current_process.cpu_since_io += 1
current_process.time_slice_remaining -= 1
cpu_busy_time += 1
# 优先检查进程是否完成
if current_process.cpu_need == 0:
current_process.state = 'DONE'
current_process.finish_time = system_time
completed_processes.append(current_process)
print(f"时间 {system_time}: PID{current_process.pid} 完成")
current_process = None
# 处理I/O阻塞
elif current_process.cpu_since_io >= current_process.io_gap and current_process.io_gap > 0:
current_process.cpu_since_io = 0
current_process.state = 'BLOCK'
current_process.block_end_time = system_time + 5 # 阻塞5ms
current_process.saved_time_slice = current_process.time_slice_remaining # 保存剩余时间片
block_queue.append(current_process)
is_block = True
print(f"时间 {system_time}: PID{current_process.pid} 进入阻塞,持续5ms")
current_process = None
# 处理时间片用尽
elif current_process.time_slice_remaining == 0:
next_level = min(current_process.queue_level + 1, 2)
current_process.queue_level = next_level
current_process.state = 'READY'
current_process.time_slice_remaining = QUEUE_CONFIG[next_level]['time_slice']
ready_queues[next_level].append(current_process)
print(f"时间 {system_time}: PID{current_process.pid} 时间片用尽,降级到Q{next_level}")
current_process = None
# 更新甘特图段
if current_segment is None:
current_segment = (system_time, current_pid, is_block)
else:
start_time, pid, block = current_segment
if pid == current_pid and block == is_block:
pass # 同一状态延续
else:
gantt_segments.append((start_time, system_time, pid, block))
current_segment = (system_time, current_pid, is_block)
system_time += 1
# 添加最后一个段
if current_segment is not None:
gantt_segments.append((current_segment[0], system_time, current_segment[1], current_segment[2]))
if system_time >= max_time:
print(f"警告:模拟时间达到上限 {max_time}ms,可能未完成所有进程。"
f"已完成: {len(completed_processes)}/{total_processes}")
return gantt_segments, completed_processes, system_time, cpu_busy_time
def print_gantt_chart(gantt_segments):
"""打印甘特图(格式完全符合任务书要求)"""
print("\n===== 甘特图(时间轴步长 1ms)=====")
print("时间区间 进程状态")
for start, end, pid, is_block in gantt_segments:
if pid is None:
continue
status = "(BLOCK)" if is_block else ""
print(f"{start:4d}-{end:4d}: PID{pid}{status}")
def calculate_performance_metrics(completed_processes, system_time, cpu_busy_time):
"""计算并打印性能指标(完全按照任务书要求)"""
total_turnaround = 0
total_weighted_turnaround = 0
total_waiting_time = 0
print("\n===== 进程性能指标 =====")
for p in completed_processes:
turnaround = p.finish_time - p.arrive
weighted_turnaround = turnaround / p.cpu_total if p.cpu_total != 0 else 0
waiting_time = turnaround - p.cpu_total
total_turnaround += turnaround
total_weighted_turnaround += weighted_turnaround
total_waiting_time += waiting_time
print(f"PID {p.pid:2d} 到达{p.arrive:3d}ms 完成{p.finish_time:3d}ms "
f"周转{turnaround:3d} 带权{weighted_turnaround:.2f} 等待{waiting_time:3d}")
if completed_processes:
avg_turnaround = total_turnaround / len(completed_processes)
cpu_utilization = (cpu_busy_time / system_time) * 100 if system_time > 0 else 0
throughput = len(completed_processes) / (system_time / 1000) if system_time > 0 else 0 # 进程/秒
print("\n===== 系统性能指标 =====")
print(f"平均周转时间: {avg_turnaround:.2f} ms")
print(f"CPU利用率: {cpu_utilization:.2f}%")
print(f"吞吐量: {throughput:.2f} 进程/秒")
else:
print("无完成的进程,无法计算系统性能指标")
return {
"avg_turnaround": avg_turnaround,
"cpu_utilization": cpu_utilization,
"throughput": throughput
}
def main():
"""主函数:执行调度模拟"""
print("===== 多级反馈队列调度模拟 =====")
# 选择输入方式
input_method = input("请选择输入方式(1:随机生成, 2:JSON文件): ")
if input_method == '1':
while True:
try:
n = int(input("请输入要生成的进程数量(≥20): "))
if n >= 20:
break
print("请至少输入20个进程!")
except ValueError:
print("请输入合法整数!")
processes = generate_processes(n)
else:
file_path = input("请输入JSON文件路径: ")
processes = load_processes_from_json(file_path)
if not processes:
return
print(f"模拟进程数: {len(processes)}")
print("进程列表(PID, 到达时间, CPU总需求, I/O间隔):")
for p in processes:
print(f"PID {p.pid:2d}: 到达{p.arrive:3d}ms, 需要{p.cpu_total:3d}ms, I/O间隔{p.io_gap:3d}ms")
# 执行调度模拟
try:
max_time = int(input("请输入最大模拟时间(ms, 默认10000): ") or "10000")
except ValueError:
max_time = 10000
gantt_segments, completed_processes, system_time, cpu_busy_time = simulate_scheduling(processes, max_time)
# 输出结果
print_gantt_chart(gantt_segments)
calculate_performance_metrics(completed_processes, system_time, cpu_busy_time)
if __name__ == "__main__":
main()