📅  最后修改于: 2023-12-03 15:28:38.656000             🧑  作者: Mango
本题是一道操作系统概念题,需要涉及进程调度、同步以及进程通信等知识点。
一台计算机有 $N$ 个进程,$P_1, P_2, ..., P_N$,每个进程都有一个固定的优先级 $P_{priority}$,值为 $0, 1, ..., N-1$,所有进程在 CPU 中轮流执行,每个进程的 CPU 时间片为 $2$。假设进程在执行时不会被打断,即不会发生中断。现有如下两个问题需要解决:
其中等待时间是指一个进程从进入就绪队列到开始执行的时间。
考虑这样一个场景:假设有两个进程 $P_1$ 和 $P_2$,它们的优先级分别为 $0$ 和 $1$,它们将交替执行,按顺序分别为 $P_1 \rightarrow P_2 \rightarrow P_1 \rightarrow P_2 \rightarrow \cdots$,每个进程的 CPU 时间片为 $2$。那么,每个进程被分配为 $2$ 个时间片。假设每个进程在进入就绪队列时都已经运行了一定时间,可以得到它们的等待时间为 $0, 2$,平均等待时间为 $\frac{0+2}{2}=1$。此时系统的吞吐率为 $\frac{2}{4}=0.5$。
接下来考虑如何最小化平均等待时间和最大化系统吞吐率。
最小化平均等待时间的核心思想是优先级高的进程优先执行。这里需要采用优先级调度算法,选择一个进程中优先级最高的进程,执行 $2$ 个时间片。
假设当前有 $n$ 个进程在就绪队列中,那么可以得到进程的平均等待时间为
$$\frac{0\times N_0 + 2\times N_1 + \cdots + (n-1)\times N_{n-1}}{n}$$
其中,$N_i$ 表示优先级为 $i$ 的进程在就绪队列中的数量。为了最小化平均等待时间,需要找到一种方法,使得每个优先级的进程在就绪队列中的等待时间相同。这可以通过循环执行进程来实现。
具体来说,可以维护 $N$ 个队列 $Q_0, Q_1, ..., Q_{N-1}$,其中第 $i$ 个队列保存所有优先级为 $i$ 的进程。每个队列中的进程都按照先来先服务(first-come first-served,FCFS)的方式进行调度。每次选择一个队列,并从队列中选择一个进程执行 $2$ 个时间片。如果当前队列为空,则直接跳过该队列。
由于每个优先级的进程都得到了相同的等待时间,所以不需要在执行过程中计算等待时间。此时进程的平均等待时间为
$$\frac{0 + 0 + \cdots + 0}{N}=0$$
因此,这种方法可以最小化平均等待时间。
最大化系统吞吐率的核心思想是尽可能多地执行进程。这里需要采用时间片轮转(time slice round-robin,TSRR)算法,每个进程都可以获得一部分 CPU 时间,从而尽可能多地执行进程。
假设每个进程的 CPU 时间段为 $T_1, T_2, ..., T_N$,其中 $T_i$ 表示第 $i$ 个进程获得 CPU 时间的总量。为了最大化系统吞吐率,每个进程都需要获得相等的 CPU 时间。
具体来说,假设每个进程的 CPU 时间片为 $q$,则每个进程可以获得 $\min(T_i, q)$ 的 CPU 时间。如果进程在所获得的时间片中没有完成执行,则将其加入就绪队列尾部,并等待下一次调度。
这种方法可以保证每个进程都能获得相等的 CPU 时间,因此可以最大化系统吞吐率。此时系统吞吐率为
$$\frac{\sum_{i=1}^N \lfloor\frac{T_i}{q}\rfloor}{\sum_{i=1}^N \lfloor\frac{T_i}{q}\rfloor + \sum_{i=1}^N (T_i \mod q)}$$
下面是参考代码,其中 process
为进程类,fcfs
函数为最小化平均等待时间的实现,tsrr
函数为最大化系统吞吐率的实现。
class Process:
def __init__(self, priority, time):
self.priority = priority
self.time = time # 进程需要的总时间
def fcfs(processes):
N = len(processes)
queue = [[] for _ in range(N)] # 优先级队列
for p in processes:
queue[p.priority].append(p)
time = 0 # 当前时间
waiting_time = [0] * N # 等待时间
while sum(map(len, queue)) > 0:
for q in queue:
if len(q) == 0:
continue
p = q.pop(0)
waiting_time[p.priority] += time
time += 2
# 将队列重新排列,确保优先级高的进程优先执行
queue = [q for q in queue if len(q) > 0] + [[] for _ in range(N)]
average_waiting_time = sum(waiting_time) / N
return average_waiting_time
def tsrr(processes, q):
N = len(processes)
queue = processes[:] # 就绪队列
time = 0 # 当前时间
waiting_time = [0] * N # 等待时间
while len(queue) > 0:
p = queue.pop(0)
t = min(p.time, q)
p.time -= t
# 计算等待时间
waiting_time[p.priority] += time
time += t
if p.time > 0:
queue.append(p)
else:
# 进程已经执行完毕
pass
average_waiting_time = sum(waiting_time) / N
throughput = sum([p.time_old for p in processes]) / time
return throughput