编程与 AI14 分钟阅读更新于 2026-08-04

进程调度怎么做:从先来先服务到多级反馈队列

围绕进程调度目标、抢占方式和常见调度算法,梳理操作系统如何在多个就绪进程之间分配处理器时间。

相关工具

进程为什么还需要调度

前面讲过,进程进入就绪状态,并不代表它马上就能使用处理器。现实中的计算机通常同时承载多个任务:一个程序可能在计算,另一个程序正在等待磁盘,还有任务需要及时响应用户输入。处理器在某一时刻只能把执行权交给有限数量的进程,操作系统因此必须不断回答一个问题:下一段时间让谁运行。

进程调度就是对处理器使用权的安排。调度器从就绪队列中挑选进程,分配一段运行机会;当进程结束、主动等待、时间片用完,或者更高优先级的任务到来时,系统再决定是否切换。调度不是把所有进程简单排成一列,而是在响应速度、公平性、吞吐量和切换开销之间寻找平衡。

多个就绪进程经过调度器获得处理器时间的示意图
调度器面对的基本问题

多个就绪进程竞争有限的处理器时间,调度器根据目标选择下一项任务。

调度算法究竟在优化什么

可以将 CPU 利用率、系统吞吐量、周转时间、等待时间和响应时间列为常见衡量指标。CPU 利用率关注处理器是否长期处于有效工作状态;吞吐量关注单位时间完成了多少任务;周转时间从任务提交开始算到任务结束,反映一次任务完整走完系统需要多久。

等待时间只统计进程在就绪队列中等待处理器的时间,响应时间则更接近用户感受:从提交请求到系统第一次给出响应,需要等多久。不同指标可能互相牵制。例如,过度追求吞吐量可能让交互任务迟迟得不到机会;过度缩短响应时间,又可能带来更频繁的上下文切换。

非抢占与抢占:执行权能不能被拿走

非抢占式调度下,进程一旦获得处理器,通常会继续运行到主动结束、主动阻塞或完成当前阶段,调度器不会因为另一个更紧急的进程到来就立刻打断它。这种方式实现相对简单,切换次数也较少,但长任务可能挡住后面的短任务。

抢占式调度允许系统在合适的时机暂停正在运行的进程,把处理器交给更重要或更紧急的任务。抢占能改善交互响应和公平性,但每次暂停都要保存现场,之后还要恢复现场,因此会产生额外开销。抢占也不能只看优先级,还要避免低优先级任务长期得不到运行机会。

非抢占式和抢占式进程调度的对比图
两种执行权转移方式

非抢占等待当前任务主动让出处理器,抢占则允许系统在调度条件满足时切换任务。

先来先服务:规则简单,但不总是公平

先来先服务,也就是 FCFS,按照进程进入就绪队列的先后顺序运行。它的规则很直观:先排队的任务先得到处理器,当前任务结束或阻塞后,再轮到后面的任务。因为不需要估计运行时间,也不需要频繁重新计算优先级,所以实现简单,行为容易解释。

它的问题在于队首的长任务会挡住后面的一串短任务。假设一个需要很久 CPU 时间的任务先进入队列,后面即使有很多只需片刻就能完成的任务,也只能继续等待。这种现象会拉长短任务的周转时间,因此 FCFS 更适合强调顺序和稳定性的场景,而不适合对交互响应要求很高的系统。

最短作业优先:提高吞吐量,也可能让长任务久等

最短作业优先,也就是 SJF,每次从就绪队列中选择预计运行时间最短的任务。短任务先完成,系统在单位时间内往往能完成更多任务,平均等待时间也可能下降。这个思路很有吸引力,因为它直接减少了短任务在长任务后面排队的时间。

但系统通常只能估计任务未来还需要运行多久,无法提前准确知道结果。更重要的是,如果短任务不断到来,长任务可能一直被推迟,形成饥饿。SJF 还没有直接表达任务的紧急程度,所以一个虽然很短但不紧急的任务,可能会排在真正重要的长任务之前。

响应比优先:让等待时间参与排序

响应比优先试图同时考虑任务的等待时间和服务时间。一个任务等待得越久,它的优先级会逐步上升;在服务时间相同的情况下,等待更久的任务更应该先得到处理。这样既保留了短任务较快完成的优势,也给长期等待的任务留下了被调度的机会。

它背后的思路很朴素:不能只看任务本身有多短,还要看它已经等了多久。等待时间持续累积后,长任务的响应比也会提高,从而减轻长期饥饿。这个算法适合用来理解调度中的折中关系,但它依然依赖对运行时间的估计,实际系统往往会采用更动态的策略。

时间片轮转:把处理器切成轮流使用的机会

时间片轮转为每个就绪进程分配一小段固定时间,称为时间片。进程获得时间片后运行;如果在时间片结束前完成或进入阻塞状态,处理器可以马上转交给其他进程;如果时间片用完仍未完成,系统保存它的运行现场,把它放回队列末尾。

时间片大小很关键。时间片太短,系统会频繁保存和恢复现场,CPU 花费在调度上的时间增加;时间片太长,短任务和交互请求的响应又会变慢。合理的时间片应该让任务有足够时间推进,同时避免某一个任务长时间占用处理器。

时间片轮转调度中多个进程循环获得处理器的流程图
时间片轮转的运行顺序

就绪队列中的进程轮流获得时间片,未完成的进程回到队尾等待下一轮。

优先级调度与多级反馈队列

优先级调度每次选择优先级更高的进程运行。优先级可以在创建任务时确定,也可以根据运行时间、等待时间和任务行为动态调整。静态优先级容易理解,但低优先级任务可能长期等不到机会;动态优先级能够缓解这个问题,却需要系统持续记录和计算。

多级反馈队列把就绪进程分到多个队列中,不同队列使用不同的优先级和时间片。新进程通常先进入优先级较高的队列,能够快速获得短时间的处理机会;如果它长期运行却一直没有完成,就会逐步降到更低的队列。这样,交互型短任务可以较快响应,持续占用 CPU 的任务也不会永久阻塞其他任务。

看懂调度现象:不要只问谁先运行

遇到“程序变慢”或“任务一直没有完成”时,不能只问哪个进程优先级最高。还要看它是否在就绪队列中等待,是否因为磁盘或网络进入阻塞,是否频繁发生上下文切换,以及它所在的队列是否长期被更高优先级任务占满。调度现象通常是多个条件共同作用的结果。

学习调度算法时,可以沿着一条固定思路观察:任务什么时候进入就绪队列,什么时候获得处理器,何时主动阻塞,何时被抢占,未完成时会回到哪个队列。把这些时间点串起来,FCFS 的排队、SJF 的短任务优先、时间片轮转的循环和多级反馈队列的降级就会变成一条连续的运行过程,而不是几组孤立的名词。

用一句话记住进程调度

进程调度是在有限处理器时间下安排任务运行顺序的机制。FCFS 重视到达顺序,SJF 重视预计运行时间,响应比优先把等待时间纳入考虑,时间片轮转强调轮流获得机会,优先级和多级反馈队列则试图同时照顾任务的重要性、响应速度与长期公平。

没有一种算法可以在所有场景中都最好。真正需要理解的是每个规则改变了什么:谁更早得到处理器,谁可能等待更久,切换成本从哪里产生,以及系统如何防止某类任务被永久忽略。

常见问题

抢占式调度一定比非抢占式调度好吗?

不一定。抢占式调度通常更有利于交互响应和任务公平,但需要承担更多上下文切换开销;非抢占式调度规则简单,适合强调顺序或切换成本较高的场景。

时间片是不是越短越好?

不是。时间片过短会导致频繁切换,降低处理器有效工作时间;过长又会让交互任务等待更久,需要在响应速度和切换成本之间取平衡。

多级反馈队列为什么能兼顾短任务和长任务?

短任务通常能在高优先级队列的有限时间片内完成,持续运行的长任务则会逐步进入较低队列继续获得处理器机会,因此同时照顾了响应速度和长期公平。