### 抢占式优先级调度与时间片轮转算法的例题解析
#### 1. 背景介绍
抢占式优先级调度是一种基于优先级的调度方法,在此策略下,CPU总是被分配给具有最高优先级的进程。如果一个新的高优先级进程进入就绪队列,则当前正在运行的低优先级进程会被中断并重新加入到等待队列中[^2]。而时间片轮转(Round Robin, RR)则通过固定的时间片来轮流执行各个进程,确保每个进程都能得到一定的 CPU 使用权[^4]。
当这两种算法结合时,通常会形成一种混合机制:既考虑优先级又兼顾公平性。下面是一个具体的例子及其解析过程。
---
#### 2. 示例题目描述
假设有一个系统中有四个进程 P1、P2、P3 和 P4 的相关信息如下:
| **进程名** | **到达时间 (ms)** | **所需服务时间 (ms)** | **初始优先级** |
|------------|---------------------|-------------------------|----------------|
| P1 | 0 | 7 | 1 |
| P2 | 2 | 4 | 2 |
| P3 | 4 | 1 | 3 |
| P4 | 5 | 4 | 2 |
- 系统采用抢占式优先级调度,并设置了一个较小的时间片 T=2 ms 来模拟时间片轮转的行为。
- 如果两个或多个进程拥有相同的优先级,则按照先来先服务的原则决定顺序。
- 动态调整规则:每当一个进程完成一次时间片内的运行后,其优先级降低一级;若某个进程因更高优先级的任务到来而被迫暂停,则不改变它的优先级。
目标是计算这些进程的实际运行次序以及它们各自的完成时间和周转时间。
---
#### 3. 解决方案详解
##### (1)初始化状态
根据上述条件建立事件序列表,记录每一个时刻的状态变化情况。最初只有 P1 到达,因此它立即开始执行。
##### (2)逐步推导每一步骤的结果
以下是详细的步骤分解和对应的图表展示:
| 当前时间(ms)| 正在运行的进程 | 剩余服务时间(P1,P2,P3,P4)(ms) | 就绪队列中的其他进程 | 更新后的优先级(P1,P2,P3,P4) |
|--------------|--------------------|------------------------------------|-------------------------------|------------------------------|
| 0 | P1 | {7, -, -, -} | [] | {1, -, -, -} |
| 2 | P1 -> Time Slice | {5, -, -, -} | [P2(2)] | {2, 2, -, -} |
| 4 | P2 | {5, 4, -, -} | [P3(4), P1(5)] | {2, 2, 3, -} |
| 6 | P2 -> Preempted | {5, 2, -, -} | [P3(4), P1(5), P4(5)] | {2, 3, 3, 2} |
| 8 | P4 | {5, 2, -, 4} | [P3(4), P1(5), P2(2)] | {2, 3, 3, 2} |
| ... | Continue similarly...| ... | ... | ... |
最终得出完整的 Gantt 图表示法如下所示:
```
Time: 0 2 4 6 8 10 12 14 16 18
Process: P1->P1->P2->P2->P4->P4->P1->P1->P3->Idle
```
##### (3)性能指标评估
对于每个单独的作业来说,我们可以进一步求解平均响应时间(Average Response Time),平均等待时间(Average Waiting Time)以及其他可能关心的数据统计量。
---
#### 4. Python 实现代码片段
为了验证以上逻辑正确与否,这里给出一段简单的 python 模拟程序作为辅助工具:
```python
class Process:
def __init__(self, name, arrival_time, burst_time, priority):
self.name = name
self.arrival_time = arrival_time
self.burst_time = burst_time
self.priority = priority
self.remaining_time = burst_time
def rr_priority_scheduler(processes, time_slice):
current_time = 0
ready_queue = []
while True:
# Add new processes that have arrived at this point.
available_procs = [p for p in processes if p.arrival_time <= current_time and not hasattr(p,'completed')]
for proc in available_procs:
if 'added' not in dir(proc):
ready_queue.append(proc)
setattr(proc,"added",True)
if len(ready_queue)==0 : break
selected_proc=None
max_prio=-float('inf')
# Select highest prio process from queue considering dynamic adjustments after each slice usage.
for idx,potential_candidate in enumerate(ready_queue[:]):
adjusted_priorities=[cand.priority-(current_time-cand.last_run)//time_slice for cand in ready_queue ]
if adjusted_priorities[idx]>max_prio :
max_prio=adjusted_priorities[idx]
selected_idx=idx
chosen_one=ready_queue.pop(selected_idx)
print(f"At t={current_time}, Running:{chosen_one.name}")
if chosen_one.remaining_time<=time_slice:
current_time += chosen_one.remaining_time
chosen_one.completed=True
delattr(chosen_one,"remaining_time")
else:
current_time+=time_slice
chosen_one.remaining_time -= time_slice
chosen_one.last_run=current_time
ready_queue.insert(len([i for i in ready_queue if getattr(i,'last_run',None)!=None]),chosen_one )
process_list=[
Process("P1",0 ,7 ,1 ),
Process("P2",2 ,4 ,2 ),
Process("P3",4 ,1 ,3 ),
Process("P4",5 ,4 ,2 )]
rr_priority_scheduler(process_list,time_slice=2)
```
---
###