PID为0的系统空闲进程连接状态为TIME_WAIT

本文解析了在网络连接中出现PID为0的SystemIdleProcess占用大量端口的原因,阐述了Time_Wait状态的作用及端口释放机制,并解释了为何这并不意味着系统受到病毒感染。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果您使用命令提示符执行命令查看网络连接情况,您会发现,PID为0的System Idle Process(系统空闲进程)将会出现很多网络端口占用情况。下面是一个示例:
Proto  Local Address          Foreign Address        State           PID
TCP    127.0.0.1:30606        127.0.0.1:3129         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3131         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3133         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3135         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3137         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3139         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3141         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3143         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3145         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3147         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3149         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3151         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3153         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3155         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3157         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3159         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3161         TIME_WAIT       0
TCP    127.0.0.1:30606        127.0.0.1:3165         TIME_WAIT       0
我们这里使用了“netstat -a -n -o”命令,参数-a用来显示所有的连接和监听端口,参数-o用来显示相应系统进程的PID,使用了参数-n以数字(IP)的方式显示地址和端口。
    那么是不是说明计算机中了病毒了呢?其实并不是这样,这要从为什么系统空闲进程要占用端口说起了。
    通过仔细观察,我们可以发现,命令结果列出的所有PID为0的通信的状态均为Time_Wait,而决不会是Established建立状态或者是Listening监听状态,这个就要涉及到一个TCP Socket的问题了,有兴趣深入研究的朋友们可以查阅一下更多的有关文章,因为概念性的东西太多了,因此我们在此仅进行一个简要的解释。
    原因是这样的:
    一、关于Time_Wait状态:
          TCP TIME-WAIT 延迟断开TCP 连接时,套接字对被置于一种称为TIME-WAIT 的状态。这样,新的连接不会使用相同的协议、源 IP 地址、目标 IP 地址、源端口和目标端口,直到经过足够长的时间后,确保任何可能被错误路由或延迟的段没有被异常传送。因此,Time_Wait不是多余的状态,而是为了保证通信的正确性、准确性而存在的。而且,这样的状态往往都交给系统空闲进程处理了,因为具体的应用程序已经完成了通信过程,发出了数据。因此,这里PID为0的通信均是已“断开”的曾经被进程使用过的连接,而且还没有释放端口。
    二、关于端口的释放:
          什么时候释放,怎样释放呢?我们将这种套接字对不被其它连接重新使用的时间长度指定为两个MSL(最大段生存时间),即4 分钟。对于Windows NT 系统来说,这是默认设置。然而,在此默认设置下,某些网络应用程序在很短时间内执行多个出站连接,也就可能会在端口收回前用完所有的可用端口。
    三、我们所看到的空闲进程端口占用的特点:
          因为总是有程序要交替或者分段连续地访问网络,而且同一个程序在端口被完全释放之前,可能还会再次使用,就算不再使用,为了保证正确通信,也要等待两个MSL,故处于Time_Wait。因此我们看到的情况是,系统空闲进程占用了一些端口,而且这些端口、端口的数量随着每次执行netstat -a -n -o命令时也会有变化。因为可能在某个处于Time_Wait的端口被完全释放之前,又有一个连接不再需要某个端口了,故新的一个端口又被置于Time_Wait状态,过了不久,前一个终于被释放了,于是您还是看到有这样的状态,但是端口是不一样的。对于一个接入网络并且安装了需要网络的应用软件的操作系统,这个过程是无限循环的,因此您总是能够看到处于Time_Wait状态的被PID=0的系统空闲进程“使用”的连接。

import random from collections import deque import json class PCB: """进程控制块(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 # 当前甘特图段 # 等待到达的进程 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. 检查新到达的进程 new_process_arrived = False 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'] ready_queues[0].append(p) print(f"时间 {system_time}: PID{p.pid} 到达,加入Q0") new_process_arrived = True # 2. 检查阻塞进程是否到期 block_process_resumed = False while block_queue and block_queue[0].block_end_time <= system_time: p = block_queue.popleft() p.state = 'READY' p.cpu_since_io = 0 # 恢复保存的时间片 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}") block_process_resumed = True # 3. 如果有新进程到达或阻塞进程恢复,检查是否需要抢占当前进程 if new_process_arrived or block_process_resumed: if current_process: # 检查是否有更高优先级的进程就绪 preempt = False for i in range(current_process.queue_level): if ready_queues[i]: preempt = True break if preempt: # 将当前进程放回就绪队列 current_process.state = 'READY' ready_queues[current_process.queue_level].append(current_process) print(f"时间 {system_time}: PID{current_process.pid} 被抢占,放回Q{current_process.queue_level}") current_process = None # 4. 调度进程(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: 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() 这段代码的输出结果我认为有问题: ===== 甘特图(时间轴步长 1ms)===== 时间区间 进程状态 0- 2: PID1 2- 4: PID2 4- 6: PID3 6- 8: PID1 8- 9: PID1(BLOCK) 9- 13: PID2 13- 14: PID3 14- 15: PID3(BLOCK) 15- 16: PID1 16- 17: PID2 17- 18: PID2(BLOCK) 18- 19: PID1 19- 21: PID3 21- 23: PID1 23- 24: PID1(BLOCK) 24- 25: PID3 25- 26: PID3(BLOCK) 26- 33: PID2 33- 34: PID2(BLOCK) 34- 39: PID1 39- 41: PID3 41- 45: PID2 我觉得还有问题,比如”13- 14: PID3 14- 15: PID3(BLOCK) 15- 16: PID1 16- 17: PID2 17- 18: PID2(BLOCK) 18- 19: PID1 19- 21: PID3 21- 23: PID1 23- 24: PID1(BLOCK)“这一段结果应该是13- 14: PID3 14- 15: PID3(BLOCK) 15- 16: PID1 16- 17: PID2 17- 18: PID2(BLOCK) 18- 20: PID1 20- 22: PID3 22- 23: PID1 23- 31: PID2(BLOCK)因为15ms时pid3进入阻塞状态20ms时PID3由阻塞状态进入队列Q1继续执行上次剩余得时间片2ms,然后耗尽Q1队列的时间片后进入队列Q1,此时在队列Q2中的进程顺序为pid2、pid1、pid3,但是由于pid2进入阻塞时的时间为18ms,他重新运行的时间应该是23ms,所以22-23mspid1先运行。你觉得我的想法正确吗
最新发布
07-01
以下是使用C语言实现单处理器系统进程调度的代码示例: ``` #include <stdio.h> #include <stdlib.h> #define MAX_PROCESS 10 #define TIME_SLICE 2 int current_time = 0; // 当前时间 int current_process = -1; // 当前正在运行的进程的编号 // 进程控制块结构体 typedef struct PCB { int pid; // 进程编号 int status; // 进程状态:0-空闲,1-就绪,2-运行,3-阻塞,4-完成 int arrival_time; // 进程到达时间 int burst_time; // 进程执行时间 int remaining_time; // 进程剩余执行时间 int wait_time; // 进程等待时间 } PCB; PCB process_table[MAX_PROCESS]; // 进程表 // 创建进程 void create_process(int pid, int arrival_time, int burst_time) { process_table[pid].pid = pid; process_table[pid].status = 0; process_table[pid].arrival_time = arrival_time; process_table[pid].burst_time = burst_time; process_table[pid].remaining_time = burst_time; process_table[pid].wait_time = 0; } // 进程调度 void schedule() { int i; // 找到最早到达的就绪进程 int earliest_ready = -1; for (i = 0; i < MAX_PROCESS; i++) { if (process_table[i].status == 1) { // 就绪状态 if (earliest_ready == -1 || process_table[i].arrival_time < process_table[earliest_ready].arrival_time) { earliest_ready = i; } } } if (current_process != -1 && process_table[current_process].remaining_time > 0) { // 当前进程未完成 process_table[current_process].status = 1; // 放回就绪队列 } if (earliest_ready != -1) { // 有就绪进程 current_process = earliest_ready; process_table[current_process].status = 2; // 运行状态 process_table[current_process].wait_time += current_time - process_table[current_process].arrival_time; // 计算等待时间 } else { // 无就绪进程 current_process = -1; } } // 进程阻塞 void block_process(int pid) { process_table[pid].status = 3; // 阻塞状态 } // 进程唤醒 void wakeup_process(int pid) { process_table[pid].status = 1; // 就绪状态 } // 主函数 int main() { int i, j; // 初始化进程表 for (i = 0; i < MAX_PROCESS; i++) { process_table[i].pid = i; process_table[i].status = 0; process_table[i].arrival_time = -1; process_table[i].burst_time = -1; process_table[i].remaining_time = -1; process_table[i].wait_time = -1; } // 创建进程 create_process(0, 0, 3); create_process(1, 1, 5); create_process(2, 2, 2); create_process(3, 3, 4); create_process(4, 4, 6); // 进程调度 while (1) { int all_done = 1; // 是否所有进程均已完成 for (i = 0; i < MAX_PROCESS; i++) { if (process_table[i].status != 4) { // 进程未完成 all_done = 0; break; } } if (all_done) { // 所有进程均已完成 break; } schedule(); if (current_process != -1) { printf("时间 %d,进程 %d 开始执行\n", current_time, current_process); for (j = 0; j < TIME_SLICE; j++) { current_time++; process_table[current_process].remaining_time--; if (process_table[current_process].remaining_time == 0) { // 进程完成 process_table[current_process].status = 4; // 完成状态 printf("时间 %d,进程 %d 完成\n", current_time, current_process); break; } } if (process_table[current_process].remaining_time > 0) { // 时间片用完,进程被抢占 printf("时间 %d,进程 %d 时间片用完,被抢占\n", current_time, current_process); process_table[current_process].status = 1; // 放回就绪队列 } } else { current_time++; } } // 输出进程等待时间 printf("进程等待时间:\n"); for (i = 0; i < MAX_PROCESS; i++) { printf("进程 %d:%d\n", i, process_table[i].wait_time); } return 0; } ``` 该程序使用时间片轮转法调度策略,每个进程被分配一个时间片,时间片用完后进程被抢占并放回就绪队列。进程表中的状态分别为0-空闲,1-就绪,2-运行,3-阻塞,4-完成。在主函数中创建了5个进程,分别为: 进程0,到达时间0,执行时间3 进程1,到达时间1,执行时间5 进程2,到达时间2,执行时间2 进程3,到达时间3,执行时间4 进程4,到达时间4,执行时间6 程序输出了每个进程开始执行和完成的时间,并在程序结束后输出了每个进程的等待时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值