Introduction
操作系统的调度中,有一个常用的调度方法叫抢占式调度。在这篇博客我将简单介绍一下抢占式优先队列,并且用C++实现一个简单的版本。
What is Preemptive Scheduling
抢占式调度出现在操作系统调度的场景中,当两个或多个任务争夺单个CPU计算资源时,就会存在谁先谁后的问题。在抢占式的模式下,优先级较高的任务能够首先被处理。
Implementation
这里我将用一个简单的例子去实现一个抢占式调度。
问题描述
一个单核CPU按优先级调度进程,进程的优先级是它们的编号,编号越小则优先级越高。输入进程数及每个进程的编号、到达时间、所需的运行时间,求CPU执行进程的顺序。
输入
第一行输入进程个数N
,之后每行输入进程编号、进程到达时间、进程所需运行时间,空格隔开。其中进程的输入顺序是按照到达顺序排序的。
样例:
1 | 4 |
输出
按照进程在CPU的执行顺序,打印进程编号。
样例:
1 | 9 7 2 7 9 4 9 |
分析
因为要根据优先级进行排序,所以很自然我们会使用优先队列。但这道题目的关键不是优先的问题,而是抢占。
我们每次都从队头中拿出一个任务,因为使用优先队列,所以这个任务的优先级肯定是最高的。然后我们要看看能处理多久。此时要引入一个变量t
,表示当前时间减去上一个进程的到达时间,这个表示的是这个时间间隔有多长。然后就是处理抢占任务:
- 如果
t
大于当前任务所需要的处理时间,则说明当前任务肯定能在当前这一刻前处理完,因此先用t
减去当前任务的处理时间,然后把当前任务从队列中移除,然后继续从队列中拿下一个任务处理,不断循环这个步骤,直至队列为空或者t < 0
(说明时间不够了); - 如果
t
小于当前任务所需要的处理时间,则说明当前任务在当前这刻肯定处理不完,因此t
可以直接置为0,同时还要计算出这个任务还剩多少没处理。计算出来之后,我们需要用这个值去更新这个任务所需要的处理时间(因为变短了),这里特别注意,不能直接修改队列中的值,而是需要把旧的任务先pop出来,然后再push回去。
最后,如果在最后一个任务到达后,还有任务没有处理完,那么直接按照优先队列里面的顺序逐个处理即可,因为此时已经不存在抢占的问题了。
代码
1 |
|