网络拓扑与进程调度结合模拟

网络拓扑与进程调度结合模拟:在 Python 中创建一个网状网络拓扑,在每个节点上模拟操作系统的进程调度(使用如 FCFS、SJF 等算法),模拟数据在网络节点间的传输过程中,同时考虑进程调度对数据传输效率和可靠性的影响。例如,当节点上的进程调度繁忙时,数据传输可能会延迟,分析这种情况下网络的整体性能。

import tkinter as tk
from tkinter import ttk, scrolledtext
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import random
import heapq
from enum import Enum
from collections import deque, defaultdict
from matplotlib.figure import Figure

# 设置随机种子以便结果可重现
random.seed(42)


class Process:
    """表示一个需要调度和执行的进程"""

    def __init__(self, pid, arrival_time, burst_time, data_size=0):
        self.pid = pid  # 进程ID
        self.arrival_time = arrival_time  # 到达时间
        self.burst_time = burst_time  # 执行时间
        self.remaining_time = burst_time  # 剩余执行时间
        self.start_time = None  # 首次执行时间
        self.completion_time = None  # 完成时间
        self.waiting_time = 0  # 等待时间
        self.turnaround_time = 0  # 周转时间
        self.data_size = data_size  # 数据大小(如果是网络相关进程)

    def __repr__(self):
        return f"Process(pid={self.pid}, arrival_time={self.arrival_time}, burst_time={self.burst_time})"


class SchedulingAlgorithm(Enum):
    """调度算法枚举"""
    FCFS = 1  # 先来先服务
    SJF = 2  # 最短作业优先
    RR = 3  # 时间片轮转


class DataPacket:
    """表示网络中的数据包"""

    def __init__(self, packet_id, source, destination, size):
        self.packet_id = packet_id  # 数据包ID
        self.source = source  # 源节点
        self.destination = destination  # 目标节点
        self.size = size  # 数据包大小(影响处理时间)
        self.arrival_time = 0  # 到达时间
        self.hops = 0  # 经过的跳数
        self.dropped = False  # 是否被丢弃
        self.current_position = None  # 当前位置(用于动画)
        self.progress = 0  # 传输进度(0-100)

    def __repr__(self):
        return f"Packet(id={self.packet_id}, size={self.size})"


class NetworkNode:
    """表示网络中的一个节点"""

    def __init__(self, node_id, x, y, scheduling_algorithm=SchedulingAlgorithm.FCFS, time_quantum=2):
        self.node_id = node_id  # 节点ID
        self.x = x  # x坐标(用于可视化)
        self.y = y  # y坐标(用于可视化)
        self.scheduling_algorithm = scheduling_algorithm  # 调度算法
        self.time_quantum = time_quantum  # 时间片大小(用于RR算法)
        self.process_queue = []  # 进程队列
        self.executing_process = None  # 当前执行的进程
        self.time = 0  # 节点内部时间
        self.finished_processes = []  # 已完成的进程
        self.network_queue = deque()  # 网络数据包队列
        self.neighbors = []  # 邻居节点列表
        self.performance_metrics = {
            'avg_waiting_time': 0,
            'avg_turnaround_time': 0,
            'throughput': 0,
            'packet_delay': []
        }
        self.current_packet = None  # 当前正在处理的数据包
        self.packet_processing_time = 0  # 处理当前数据包的剩余时间
        self.active_packets = []  # 正在从该节点发送的数据包

    def add_neighbor(self, neighbor_node):
        """添加邻居节点"""
        self.neighbors.append(neighbor_node)

    def add_process(self, process):
        """添加新进程到队列"""
        process.arrival_time = self.time  # 设置到达时间为当前节点时间
        self.process_queue.append(process)

    def add_packet(self, packet):
        """添加数据包到网络队列"""
        packet.arrival_time = self.time  # 记录到达时间
        self.network_queue.append(packet)

    def update_performance_metrics(self):
        """更新性能指标"""
        if self.finished_processes:
            total_waiting_time = sum(p.waiting_time for p in self.finished_processes)
            total_turnaround_time = sum(p.turnaround_time for p in self.finished_processes)

            self.performance_metrics['avg_waiting_time'] = total_waiting_time / len(self.finished_processes)
            self.performance_metrics['avg_turnaround_time'] = total_turnaround_time / len(self.finished_processes)

        if self.performance_metrics['packet_delay']:
            self.performance_metrics['throughput'] = len(self.performance_metrics['packet_delay']) / max(1, self.time)

    def select_next_process(self):
        """根据调度算法选择下一个要执行的进程"""
        if not self.process_queue:
            return None

        if self.scheduling_algorithm == SchedulingAlgorithm.FCFS:
            # 按到达时间排序
            self.process_queue.sort(key=lambda p: p.arrival_time)
            return self.process_queue.pop(0)

        elif self.scheduling_algorithm == SchedulingAlgorithm.SJF:
            # 按执行时间排序(最短作业优先)
            self.process_queue.sort(key=lambda p: p.burst_time)
            return self.process_queue.pop(0)

        elif self.scheduling_algorithm == SchedulingAlgorithm.RR:
            # 轮转调度:从队列头部取出,执行一个时间片后放回尾部
            if not hasattr(self, 'rr_queue'):
                self.rr_queue = deque(self.process_queue)
                self.process_queue = []

            if not self.rr_queue:
                return None

            process = self.rr_queue.popleft()
            return process

        return None

    def process_packet(self):
        """处理网络数据包"""
        if self.current_packet is None and self.network_queue:
            self.current_packet = self.network_queue.popleft()
            # 处理时间与数据包大小成正比
            self.packet_processing_time = self.current_packet.size

        if self.current_packet is not None:
            # 处理数据包
            self.packet_processing_time -= 1

            if self.packet_processing_time <= 0:
                # 数据包处理完成,转发到下一个节点
                self.forward_packet(self.current_packet)

                # 记录延迟
                delay = self.time - self.current_packet.arrival_time
                self.performance_metrics['packet_delay'].append(delay)

                self.current_packet = None
                self.packet_processing_time = 0

    def forward_packet(self, packet):
        """将数据包转发到下一个节点"""
        if not self.neighbors:
            # 没有邻居节点,数据包丢弃
            packet.dropped = True
            return

        # 随机选择一个邻居节点转发
        next_node = random.choice(self.neighbors)

        # 设置数据包的当前位置和目标位置
        packet.current_position = (self.x, self.y)
        packet.target_node = next_node
        packet.progress = 0

        # 添加到活动数据包列表
        self.active_packets.append(packet)

    def execute(self, time_units=1):
        """执行一个时间单位的模拟"""
        execution_log = []

        for _ in range(time_units):
            self.time += 1

            # 更新活动数据包的位置
            for packet in self.active_packets[:]:
                packet.progress += 10  # 每次更新10%的进度

                if packet.progress >= 100:
                    # 数据包到达目标节点
                    packet.hops += 1
                    packet.target_node.add_packet(packet)
                    self.active_packets.remove(packet)

            # 处理网络数据包
            self.process_packet()

            # 如果当前有执行的进程,继续执行
            if self.executing_process:
                self.executing_process.remaining_time -= 1

                # 记录执行信息
                log_entry = f"时间 {self.time}: 节点 {self.node_id} 正在执行进程 {self.executing_process.pid} " \
                            f"(剩余时间: {self.executing_process.remaining_time})"
                execution_log.append(log_entry)

                # 检查进程是否完成
                if self.executing_process.remaining_time <= 0:
                    self.executing_process.completion_time = self.time
                    self.executing_process.turnaround_time = self.executing_process.completion_time - self.executing_process.arrival_time
                    self.executing_process.waiting_time = self.executing_process.turnaround_time - self.executing_process.burst_time
                    self.finished_processes.append(self.executing_process)

                    # 记录完成信息
                    log_entry = f"时间 {self.time}: 节点 {self.node_id} 完成进程 {self.executing_process.pid} " \
                                f"(周转时间: {self.executing_process.turnaround_time}, 等待时间: {self.executing_process.waiting_time})"
                    execution_log.append(log_entry)

                    # 如果是网络数据包相关的进程,处理完后创建数据包
                    if self.executing_process.data_size > 0:
                        packet = DataPacket(
                            packet_id=len(self.performance_metrics['packet_delay']) + 1,
                            source=self,
                            destination=None,  # 目的地将在网络层确定
                            size=self.executing_process.data_size
                        )
                        self.add_packet(packet)

                        log_entry = f"时间 {self.time}: 节点 {self.node_id} 生成数据包 {packet.packet_id} (大小: {packet.size})"
                        execution_log.append(log_entry)

                    self.executing_process = None

                    # 如果是RR算法,检查队列中是否有更多进程
                    if self.scheduling_algorithm == SchedulingAlgorithm.RR and hasattr(self,
                                                                                       'rr_queue') and self.rr_queue:
                        self.executing_process = self.rr_queue.popleft()

                # 对于RR算法,检查时间片是否用完
                elif self.scheduling_algorithm == SchedulingAlgorithm.RR:
                    # 减少时间片计数
                    if not hasattr(self, 'time_quantum_count'):
                        self.time_quantum_count = self.time_quantum

                    self.time_quantum_count -= 1

                    if self.time_quantum_count <= 0:
                        # 时间片用完,将进程放回队列尾部
                        self.rr_queue.append(self.executing_process)
                        self.executing_process = None
                        self.time_quantum_count = self.time_quantum

            # 如果当前没有执行的进程,选择一个新进程
            if self.executing_process is None:
                self.executing_process = self.select_next_process()

                if self.executing_process:
                    if self.executing_process.start_time is None:
                        self.executing_process.start_time = self.time

                    # 记录开始执行信息
                    log_entry = f"时间 {self.time}: 节点 {self.node_id} 开始执行进程 {self.executing_process.pid} " \
                                f"(执行时间: {self.executing_process.burst_time})"
                    execution_log.append(log_entry)

            # 更新性能指标
            self.update_performance_metrics()

        return execution_log


class MeshNetwork:
    """表示网状网络拓扑"""

    def __init__(self, num_nodes, connectivity=2, scheduling_algorithm=SchedulingAlgorithm.FCFS, time_quantum=2):
        self.num_nodes = num_nodes  # 节点数量
        self.connectivity = connectivity  # 每个节点的连接数
        self.nodes = []  # 节点列表
        self.time = 0  # 网络全局时间
        self.scheduling_algorithm = scheduling_algorithm
        self.time_quantum = time_quantum
        self.execution_logs = []  # 执行日志

        # 创建节点(环形布局)
        angles = np.linspace(0, 2 * np.pi, num_nodes, endpoint=False)
        radius = 200  # 圆环半径

        for i in range(num_nodes):
            x = 250 + radius * np.cos(angles[i])  # +250是为了将图形居中
            y = 250 + radius * np.sin(angles[i])

            node = NetworkNode(
                node_id=i,
                x=x,
                y=y,
                scheduling_algorithm=scheduling_algorithm,
                time_quantum=time_quantum
            )
            self.nodes.append(node)

        # 构建网状连接
        self.build_mesh_topology()

    def build_mesh_topology(self):
        """构建网状拓扑结构"""
        # 使用环形连接作为基础,然后添加随机连接
        for i in range(self.num_nodes):
            # 连接到下一个节点(形成环)
            next_node = (i + 1) % self.num_nodes
            self.nodes[i].add_neighbor(self.nodes[next_node])

            # 添加额外的随机连接
            for _ in range(self.connectivity - 1):
                # 随机选择一个不相邻的节点
                possible_neighbors = [j for j in range(self.num_nodes)
                                      if j != i and j != next_node and j not in [n.node_id for n in
                                                                                 self.nodes[i].neighbors]]

                if possible_neighbors:
                    neighbor_idx = random.choice(possible_neighbors)
                    self.nodes[i].add_neighbor(self.nodes[neighbor_idx])

    def generate_processes(self, num_processes_per_node, burst_time_range=(1, 10), data_size_range=(1, 5)):
        """为每个节点生成随机进程"""
        for node in self.nodes:
            for i in range(num_processes_per_node):
                burst_time = random.randint(*burst_time_range)
                # 50%的概率是网络相关进程,需要生成数据包
                data_size = random.randint(*data_size_range) if random.random() > 0.5 else 0

                process = Process(
                    pid=f"{node.node_id}-{i}",
                    arrival_time=0,  # 将在节点添加进程时设置
                    burst_time=burst_time,
                    data_size=data_size
                )

                node.add_process(process)

    def run_simulation(self, time_units=1):
        """运行模拟指定的时间单位"""
        all_logs = []

        for _ in range(time_units):
            self.time += 1

            # 每个节点执行一个时间单位
            for node in self.nodes:
                logs = node.execute()
                all_logs.extend(logs)

        self.execution_logs.extend(all_logs)
        return all_logs

    def get_average_performance(self):
        """获取整个网络的平均性能指标"""
        avg_metrics = {
            'avg_waiting_time': 0,
            'avg_turnaround_time': 0,
            'avg_throughput': 0,
            'avg_packet_delay': 0,
            'avg_hops': 0,
            'completed_processes': 0,
            'total_processes': 0
        }

        all_delays = []
        all_hops = []

        for node in self.nodes:
            avg_metrics['avg_waiting_time'] += node.performance_metrics['avg_waiting_time']
            avg_metrics['avg_turnaround_time'] += node.performance_metrics['avg_turnaround_time']
            avg_metrics['avg_throughput'] += node.performance_metrics['throughput']
            all_delays.extend(node.performance_metrics['packet_delay'])
            all_hops.extend([p.hops for p in node.performance_metrics['packet_delay'] if hasattr(p, 'hops')])
            avg_metrics['completed_processes'] += len(node.finished_processes)
            avg_metrics['total_processes'] += len(node.finished_processes) + len(node.process_queue)
            if hasattr(node, 'rr_queue'):
                avg_metrics['total_processes'] += len(node.rr_queue)

        # 计算平均值
        if self.nodes:
            avg_metrics['avg_waiting_time'] /= len(self.nodes)
            avg_metrics['avg_turnaround_time'] /= len(self.nodes)
            avg_metrics['avg_throughput'] /= len(self.nodes)

        if all_delays:
            avg_metrics['avg_packet_delay'] = sum(all_delays) / len(all_delays)

        if all_hops:
            avg_metrics['avg_hops'] = sum(all_hops) / len(all_hops)

        return avg_metrics

    def visualize_network(self, canvas):
        """在给定的画布上可视化网络拓扑结构和数据包传输"""
        # 清除画布
        canvas.delete("all")

        # 绘制节点间的连接
        for node in self.nodes:
            for neighbor in node.neighbors:
                if node.node_id < neighbor.node_id:  # 避免重复绘制
                    canvas.create_line(node.x, node.y, neighbor.x, neighbor.y, fill="#CCCCCC", width=1)

        # 绘制节点
        node_colors = ["#3498db", "#e74c3c", "#2ecc71", "#f39c12", "#9b59b6",
                       "#1abc9c", "#d35400", "#27ae60", "#8e44ad", "#c0392b"]

        for i, node in enumerate(self.nodes):
            color = node_colors[i % len(node_colors)]

            # 节点圆圈
            canvas.create_oval(node.x - 15, node.y - 15, node.x + 15, node.y + 15, fill=color, outline="black")

            # 节点ID文本
            canvas.create_text(node.x, node.y, text=str(node.node_id), fill="white", font=("Arial", 10, "bold"))

            # 显示节点上的进程数量
            process_count = len(node.process_queue)
            if hasattr(node, 'rr_queue'):
                process_count += len(node.rr_queue)
            if node.executing_process:
                process_count += 1

            canvas.create_text(node.x, node.y + 25, text=f"进程:{process_count}", fill="black", font=("Arial", 9))

            # 显示节点上的数据包数量
            packet_count = len(node.network_queue)
            if node.current_packet:
                packet_count += 1

            canvas.create_text(node.x, node.y + 40, text=f"数据包:{packet_count}", fill="black", font=("Arial", 9))

        # 绘制活动数据包
        for node in self.nodes:
            for packet in node.active_packets:
                # 计算数据包的当前位置
                target_x, target_y = packet.target_node.x, packet.target_node.y
                progress = packet.progress / 100.0

                current_x = node.x + (target_x - node.x) * progress
                current_y = node.y + (target_y - node.y) * progress

                # 根据数据包大小确定圆圈大小
                size_factor = 5 + packet.size * 2

                # 绘制数据包
                canvas.create_oval(current_x - size_factor / 2, current_y - size_factor / 2,
                                   current_x + size_factor / 2, current_y + size_factor / 2,
                                   fill="#f1c40f", outline="black")

                # 绘制数据包ID
                canvas.create_text(current_x, current_y, text=str(packet.packet_id), fill="black", font=("Arial", 8))


class NetworkSimulationGUI:
    """网络模拟图形界面"""

    def __init__(self, root):
        self.root = root
        self.root.title("网络拓扑与进程调度模拟")
        self.root.geometry("1200x700")

        # 创建主框架
        main_frame = ttk.Frame(root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 左侧框架 - 网络可视化
        left_frame = ttk.LabelFrame(main_frame, text="网络传输模拟")
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 创建画布用于网络可视化
        self.network_canvas = tk.Canvas(left_frame, width=500, height=500, bg="white")
        self.network_canvas.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 控制面板
        control_frame = ttk.Frame(left_frame)
        control_frame.pack(fill=tk.X, padx=5, pady=5)

        ttk.Label(control_frame, text="时间片大小:").pack(side=tk.LEFT, padx=5)
        self.time_quantum_var = tk.IntVar(value=2)
        ttk.Entry(control_frame, textvariable=self.time_quantum_var, width=5).pack(side=tk.LEFT, padx=5)

        ttk.Label(control_frame, text="调度算法:").pack(side=tk.LEFT, padx=5)
        self.algorithm_var = tk.StringVar(value="RR")
        algorithm_combo = ttk.Combobox(control_frame, textvariable=self.algorithm_var,
                                       values=["FCFS", "SJF", "RR"], width=8)
        algorithm_combo.pack(side=tk.LEFT, padx=5)

        self.run_button = ttk.Button(control_frame, text="运行模拟", command=self.run_simulation)
        self.run_button.pack(side=tk.LEFT, padx=5)

        self.step_button = ttk.Button(control_frame, text="单步执行", command=self.step_simulation)
        self.step_button.pack(side=tk.LEFT, padx=5)

        self.reset_button = ttk.Button(control_frame, text="重置", command=self.reset_simulation)
        self.reset_button.pack(side=tk.LEFT, padx=5)

        self.analysis_button = ttk.Button(control_frame, text="性能分析", command=self.show_analysis)
        self.analysis_button.pack(side=tk.LEFT, padx=5)

        # 右侧框架 - 运行信息
        right_frame = ttk.LabelFrame(main_frame, text="运行信息")
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 创建文本区域用于显示日志
        self.log_text = scrolledtext.ScrolledText(right_frame, wrap=tk.WORD, height=20)
        self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 创建状态栏
        self.status_var = tk.StringVar(value="就绪")
        self.status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

        # 初始化网络
        self.reset_simulation()

    def reset_simulation(self):
        """重置模拟"""
        # 清空日志
        self.log_text.delete(1.0, tk.END)

        # 获取算法设置
        algorithm_map = {
            "FCFS": SchedulingAlgorithm.FCFS,
            "SJF": SchedulingAlgorithm.SJF,
            "RR": SchedulingAlgorithm.RR
        }
        algorithm = algorithm_map[self.algorithm_var.get()]
        time_quantum = self.time_quantum_var.get()

        # 创建网络
        self.network = MeshNetwork(
            num_nodes=10,
            connectivity=3,
            scheduling_algorithm=algorithm,
            time_quantum=time_quantum
        )

        # 为每个节点生成进程
        self.network.generate_processes(num_processes_per_node=5)

        # 更新可视化
        self.network.visualize_network(self.network_canvas)

        # 更新状态栏
        self.status_var.set(f"模拟已重置 - 时间: {self.network.time}")

        # 启用按钮
        self.run_button.config(state=tk.NORMAL)
        self.step_button.config(state=tk.NORMAL)
        self.analysis_button.config(state=tk.NORMAL)

        # 添加初始日志
        self.log_text.insert(tk.END, "模拟已重置\n")
        self.log_text.insert(tk.END, f"使用调度算法: {self.algorithm_var.get()}\n")
        self.log_text.insert(tk.END, f"时间片大小: {time_quantum}\n\n")

    def step_simulation(self):
        """单步执行模拟"""
        if not hasattr(self, 'network'):
            self.reset_simulation()

        # 执行一个时间单位
        logs = self.network.run_simulation(time_units=1)

        # 更新可视化
        self.network.visualize_network(self.network_canvas)

        # 更新日志
        for log in logs:
            self.log_text.insert(tk.END, log + "\n")
            self.log_text.see(tk.END)  # 滚动到底部

        # 更新状态栏
        self.status_var.set(f"模拟运行中 - 时间: {self.network.time}")

    def run_simulation(self):
        """运行完整模拟"""
        if not hasattr(self, 'network'):
            self.reset_simulation()

        # 禁用按钮防止重复点击
        self.run_button.config(state=tk.DISABLED)
        self.step_button.config(state=tk.DISABLED)

        # 更新状态栏
        self.status_var.set(f"模拟运行中 - 时间: {self.network.time}")

        # 运行50个时间单位
        for _ in range(50):
            logs = self.network.run_simulation(time_units=1)

            # 更新可视化
            self.network.visualize_network(self.network_canvas)

            # 更新日志
            for log in logs:
                self.log_text.insert(tk.END, log + "\n")
                self.log_text.see(tk.END)  # 滚动到底部

            # 更新状态栏
            self.status_var.set(f"模拟运行中 - 时间: {self.network.time}")

            # 让界面有时间更新
            self.root.update_idletasks()

        # 重新启用按钮
        self.run_button.config(state=tk.NORMAL)
        self.step_button.config(state=tk.NORMAL)

        # 更新状态栏
        self.status_var.set(f"模拟完成 - 时间: {self.network.time}")

    def show_analysis(self):
        """显示性能分析窗口"""
        if not hasattr(self, 'network'):
            self.reset_simulation()

        # 创建新窗口
        analysis_window = tk.Toplevel(self.root)
        analysis_window.title("性能分析")
        analysis_window.geometry("800x600")

        # 创建标签页
        notebook = ttk.Notebook(analysis_window)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 性能指标标签页
        metrics_frame = ttk.Frame(notebook)
        notebook.add(metrics_frame, text="性能指标")

        # 获取性能指标
        metrics = self.network.get_average_performance()

        # 创建性能指标表格
        metrics_tree = ttk.Treeview(metrics_frame, columns=("指标", "值"), show="headings")
        metrics_tree.heading("指标", text="性能指标")
        metrics_tree.heading("值", text="数值")
        metrics_tree.column("指标", width=300)
        metrics_tree.column("值", width=150)
        metrics_tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 添加性能指标
        metrics_tree.insert("", tk.END, values=("平均等待时间", f"{metrics['avg_waiting_time']:.2f}"))
        metrics_tree.insert("", tk.END, values=("平均周转时间", f"{metrics['avg_turnaround_time']:.2f}"))
        metrics_tree.insert("", tk.END, values=("吞吐量", f"{metrics['avg_throughput']:.2f}"))
        metrics_tree.insert("", tk.END, values=("平均数据包延迟", f"{metrics['avg_packet_delay']:.2f}"))
        metrics_tree.insert("", tk.END, values=("平均跳数", f"{metrics['avg_hops']:.2f}"))
        metrics_tree.insert("", tk.END, values=("已完成进程数", f"{metrics['completed_processes']}"))
        metrics_tree.insert("", tk.END, values=("总进程数", f"{metrics['total_processes']}"))

        # 算法分析标签页
        analysis_frame = ttk.Frame(notebook)
        notebook.add(analysis_frame, text="算法分析")

        # 添加分析文本
        analysis_text = scrolledtext.ScrolledText(analysis_frame, wrap=tk.WORD)
        analysis_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        analysis_content = """
进程调度算法分析

1. 最短作业优先(SJF)算法

优点:
- 平均等待时间和周转时间通常最优,能有效提高系统吞吐量
- 短作业能够快速完成,减少了整体响应时间
- 在作业执行时间差异较大的情况下表现尤为出色

缺点:
- 需要预先知道作业执行时间,这在实际系统中往往难以实现
- 对长作业不利,可能导致长作业长时间得不到处理(饥饿现象)
- 无法适应动态到达的作业流

适用场景:
- 批处理系统,作业执行时间可预测的场景
- 作业执行时间差异较大的环境
- 对系统吞吐量要求较高的场景


2. 时间片轮转(RR)算法

优点:
- 公平性好,每个进程都能在一定时间内得到处理
- 响应时间快,适合交互式系统,用户体验较好
- 实现简单,不需要预先知道作业执行时间

缺点:
- 时间片设置过小将增加上下文切换开销,降低系统效率
- 时间片设置过大则退化为FCFS算法,失去RR的优势
- 平均周转时间通常比SJF长

适用场景:
- 分时系统,需要快速响应的交互式系统
- 作业执行时间相近的环境
- 对公平性要求较高的场景


3. 先来先服务(FCFS)算法

优点:
- 实现简单,公平性较好
- 没有饥饿现象,每个进程最终都会被执行

缺点:
- 长作业可能导致短作业长时间等待
- 平均等待时间和周转时间通常不是最优
- 不适合需要快速响应的系统

适用场景:
- 对响应时间要求不高的批处理系统
- 作业执行时间相近的环境


在本次模拟中:
- 平均等待时间为 {avg_waiting_time:.2f}
- 平均周转时间为 {avg_turnaround_time:.2f}
- 吞吐量为 {avg_throughput:.2f}
- 平均数据包延迟为 {avg_packet_delay:.2f}

结论:
- 选择调度算法时,需要根据系统类型、作业特性和性能目标综合考虑
- 对于网络环境,RR算法通常更适合,因为它提供了更好的公平性和响应时间
- 时间片大小对RR算法的性能影响很大,需要根据系统特性合理设置
        """.format(**metrics)

        analysis_text.insert(tk.END, analysis_content)
        analysis_text.config(state=tk.DISABLED)  # 设为只读

        # 性能比较标签页
        compare_frame = ttk.Frame(notebook)
        notebook.add(compare_frame, text="算法比较")

        # 添加比较按钮
        compare_button = ttk.Button(compare_frame, text="比较不同算法",
                                    command=lambda: self.compare_algorithms(compare_frame))
        compare_button.pack(pady=10)

        # 初始显示提示信息
        ttk.Label(compare_frame, text="点击上方按钮比较不同调度算法的性能").pack(pady=20)

    def compare_algorithms(self, parent_frame):
        """比较不同调度算法的性能"""
        # 清除现有内容
        for widget in parent_frame.winfo_children():
            widget.destroy()

        # 创建图表
        fig = Figure(figsize=(7, 5), dpi=100)

        # 获取当前网络配置
        num_nodes = self.network.num_nodes
        connectivity = self.network.connectivity

        # 比较三种算法
        algorithms = [
            (SchedulingAlgorithm.FCFS, "FCFS"),
            (SchedulingAlgorithm.SJF, "SJF"),
            (SchedulingAlgorithm.RR, "RR")
        ]

        results = {}

        for algorithm, name in algorithms:
            # 创建新的网络实例
            network = MeshNetwork(
                num_nodes=num_nodes,
                connectivity=connectivity,
                scheduling_algorithm=algorithm,
                time_quantum=self.time_quantum_var.get()
            )

            # 生成相同的进程集
            network.generate_processes(num_processes_per_node=5)

            # 运行模拟
            for _ in range(50):
                network.run_simulation(time_units=1)

            # 收集结果
            results[name] = network.get_average_performance()

        # 绘制比较图表
        metrics = ['avg_waiting_time', 'avg_turnaround_time', 'avg_throughput', 'avg_packet_delay']
        metric_names = ['平均等待时间', '平均周转时间', '吞吐量', '平均数据包延迟']

        for i, metric in enumerate(metrics):
            ax = fig.add_subplot(2, 2, i + 1)
            values = [results[alg][metric] for alg in results.keys()]

            ax.bar(results.keys(), values, color=['blue', 'green', 'orange'])
            ax.set_title(metric_names[i])
            ax.set_ylabel(metric_names[i].split('(')[0])

            # 添加数值标签
            for j, v in enumerate(values):
                ax.text(j, v + 0.05 * max(values), f'{v:.2f}', ha='center')

        fig.tight_layout()

        # 在Tkinter中显示图表
        canvas = FigureCanvasTkAgg(fig, master=parent_frame)
        canvas.draw()
        canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)


if __name__ == "__main__":
    root = tk.Tk()
    app = NetworkSimulationGUI(root)
    root.mainloop()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值