什么是进程调度
当计算机中有多个process处于ready状态,将CPU分配给哪个进程呢?操作系统中做出这个决策的组件就是调度器,决策的算法叫调度算法,决策过程就是进程调度的过程。
什么时间做进程调度
进程调度一般发生在一下几种情况下:
- 进程创建
子进程被创建之后,OS需要决定继续执行父进程还是先去执行子进程 - 进程结束
- 进程block
进程结束或block后,OS要从已经ready的进程中选一个来执行 - 发生IO中断
IO中断发生时,某个进程会从block状态变为ready状态,OS需要决定是否要执行这个新ready的进程 - 发生时钟中断
在时间片调度中,每个进程被分配固定的时间片,时间片用完需要回到ready状态,换下一个进程执行,此时要进行进程调度
抢占式调度preemptive和非抢占式调度nonpreemptive
在非抢占式调度中,进程开始执行以后,除非它主动放弃CPU或被block, 否则就能一直执行。
抢占式调度中,如果在进程执行过程中来了一个优先级更高的进程,CPU使用权就会被抢走,尤其在时间片调度中即使时间片没用完也可以被抢占。但抢占也不是随时可以发生的,如果设计不好可能会发生优先级逆转或者死锁问题。
什么是好的调度算法
在不同的场景下,为了实现不同的目标,评价调度算法的标准不尽相同。这里我们介绍一些常用的标准:
Fairness: 给每个进程公平的CPU使用机会
Balance: 让系统的各个组件都能得到最大程度的利用率
Throughput 吞吐量:单位时间内完成的任务数量
Turnaround Time:一般在批处理系统中,一个批任务从提交到结束的间隔时间
CPU Utilization:CPU的利用率
Waiting Time:进程在ready队列里等待的时间
Response Time:一般在交互式系统中,从用户提交任务到第一次得到响应(任务不一定完成)的间隔时间
Meeting Deadline:一般在实时系统中及时处理数据,避免丢失或失效
如何实现进程调度
接下来我们看看在三种不同类型系统中常用的调度算法。
批处理系统中的进程调度
1. FCFS : First Come, First Served
这是一种非抢占式的先来先服务算法。ready process队列只有一个。如果进程执行中被block,进入block队列,ready之后作为新的进程排到ready队列的尾部。
优点:容易理解,容易实现
缺点:平均等待时间往往很长,不好平衡CPU密集和IO密集型进程
2. SJF: Shortest Job First
SJF也是非抢占式调度,每次都选择最短的任务来执行。
3. Shortest Remaining Time Next
是SJF的抢占式版本,只要有新任务到达就重新调度选择剩余时间最短的任务执行。
SJF和Shortest Remaining Time Next的问题在于一般情况下很难判断进程的剩余执行时间是多少。除非这是经常要执行的task,根据对历史的统计分析能确定一个执行时间的大致范围。
交互式系统中的进程调度
1. Round-Robin Scheduling
轮询调度。 给每个进程相同的时间片,轮流执行。一般时间片选择在20-50msec比较合适,太短会导致进程切换浪费时间,太长会导致响应时间延长。
优点:比SJF响应快
缺点:turnaround时间长
2. Priority Scheduling
优先级调度为每个进程分配优先级,高优先级先执行,这也是时间片调度算法。优先级可以静态分配也可以动态分配,为了避免高优先级的进程一直占用CPU不放,可以在依次执行结束后降低其优先级。相同优先级的进程之间可以使用其他的调度算法如round-robin,不同队列可以使用不同的调度算法。
优点:引入了优先级
3. Multiple Queues
为了避免执行时间长的进程频繁进程切换,可以在不同的优先级队列之间分配不等长度的时间片。进程执行一次之后被分配其他拥有更长执行时间的优先级。比如一个进程需要100个quanta, 第一次执行时分配1个,下一次执行分配2个,再下次分配4,8,16,32,64. 比每次都只分配1的纯轮询算法减少了进程调度的次数。
4. Guaranteed Scheduling
前面提到的算法都不保证进程能够得到的CPU时间,但有些情况下我们需要确保进程使用CPU的机会和时间,比如n个用户同时登录,一般要保证每个用户都能获得1/n的CPU,或者我们购买VPN服务,根据不同的用户级别需要获得一定的带宽保证。这种算法就叫Guaranteed 调度。在实现中,需要追踪给每个进程分配的CPU,与承诺分配量比较,比值最小的进程会获得下一次使用权。
5. Lottery Scheduling
彩票调度算法引入了随机性,为每个进程发一张彩票,调度时就像开奖,谁中奖谁获得资源。优先级更高的进程可以获得多张彩票以提高中奖机会。
彩票调度有趣的地方在于进程之间可以互赠彩票,比如process 1 pending在process 2上,它可以把自己的彩票都给process2提高它被调度的机会。process2结束以后再把彩票还给process1.
6. Fair-Share Scheduling
下面考虑一种情况,所有进程并不属于一个用户,这在Linux 系统中非常常见。如果user1有99个process,user2只有1个process,按照前面的算法可能user1能得到99%的CPU,而user2只有1%。为了实现用户层面的公平性,调度时需要考虑进程属于哪个user.
实时系统中的进程调度
实时系统分两种:
- 硬实时:deadline必须满足
- 软实时:偶尔错过deadline也是可以的
实时系统中,一般任务时间都比较短,调度器需要使所有进程都在deadline前完成。对于周期性发生的事件,如果事件发生的周期为, 事件处理时间(需要占用CPU的时间)为, 只有时,才是可调度的。
Separate Policy and Mechainsm
调度算法只能由操作系统实现吗,关于使用哪种调度算法进程是否有话语权呢?答案是可以的。将机制与策略分离,由操作系统提供多种实现机制,并提供system call由process传参数给OS指定具体使用哪一种调度策略。
线程调度
如果线程是在用户态实现的,那么需要两级调度,OS负责调度process,process负责调度thread。如果线程是在内核态实现的,OS直接调度thread,而不关心它属于哪个process。