在 Linux 面试中,关于实时调度策略的问题几乎是绕不开的。尤其是当面试官问出“SCHED_FIFO 和 SCHED_RR 有什么区别”时,很多人会简单回答“一个先进先出,一个时间片轮转”,然后就没了下文。这样的回答只能算及格,距离让面试官眼前一亮还有很大差距。本文将从面试实战角度出发,帮你梳理一套完整的回答框架,让你不仅能答对,还能答出深度。
一、先搞清楚:为什么需要实时调度策略
在回答具体策略之前,先要理解 Linux 调度器的整体设计。Linux 的调度策略分为两大类:
- 普通调度策略:SCHED_OTHER(也叫 SCHED_NORMAL)、SCHED_BATCH、SCHED_IDLE,它们基于 CFS(完全公平调度器)运行,追求的是公平性和吞吐量。
- 实时调度策略:SCHED_FIFO 和 SCHED_RR,它们基于实时调度器运行,追求的是确定性和低延迟。
实时任务的优先级范围是 199,数值越大优先级越高。而普通任务的优先级是 0(nice 值映射到 -2019)。这意味着:只要有一个实时任务处于可运行状态,普通任务就永远得不到 CPU,除非实时任务主动让出或阻塞。
面试时如果能先把这个背景交代清楚,面试官就知道你不是死记硬背,而是真正理解了调度器的层次结构。
二、SCHED_FIFO:先进先出,不撞南墙不回头
SCHED_FIFO 的全称是 First In First Out,它的核心规则可以用一句话概括:一旦占有 CPU,就一直运行,直到它主动放弃或被更高优先级的任务抢占。
具体来说,SCHED_FIFO 任务在以下情况才会让出 CPU:
- 主动阻塞:比如等待 I/O、等待信号量、调用 sleep 等。
- 主动让出:调用 sched_yield(),此时它会排到同优先级队列的末尾。
- 被更高优先级的实时任务抢占:注意,只有严格更高优先级的任务才能抢占它,同优先级的任务不行。
- 任务终止。
这里有一个面试常考的细节:同优先级的 SCHED_FIFO 任务之间不会互相抢占。如果两个同优先级的 FIFO 任务同时可运行,先运行的那个会一直跑到自己阻塞为止,另一个只能干等。这正是 FIFO 名字的含义——先来的先服务,服务完才轮到下一个。
这也引出了 SCHED_FIFO 的一个经典风险:如果程序员写了一个死循环且不阻塞的 FIFO 任务,它会永久霸占 CPU,导致同优先级及更低优先级的任务全部饿死,甚至可能让系统失去响应。 在面试中提到这一点,能体现你对生产环境风险的认知。
三、SCHED_RR:时间片轮转,同优先级公平
SCHED_RR 的全称是 Round Robin,它本质上是在 SCHED_FIFO 的基础上增加了时间片机制。
SCHED_RR 的规则是:
- 每个 SCHED_RR 任务被分配一个固定的时间片(在 Linux 中可以通过 sched_rr_get_interval() 获取,默认值通常与 HZ 相关)。
- 当任务的时间片用完时,它会被放到同优先级队列的末尾,让同优先级的其他 RR 任务运行。
- 不同优先级之间,高优先级任务依然可以抢占低优先级任务。
所以,SCHED_RR 可以理解为:不同优先级之间是抢占关系,同优先级之间是轮转关系。 而 SCHED_FIFO 在同优先级之间是“独占到底”的关系。
这里有一个容易被忽略的点:SCHED_RR 的时间片只对同优先级的任务轮转有效。 如果系统中只有一个 RR 任务在运行,它并不会因为时间片用完而被切换出去,因为没有其他同优先级的任务可运行,调度器会继续让它运行。
四、面试回答的核心对比框架
如果面试官让你直接对比两者,建议用下面的结构来回答,既清晰又有条理:
相同点:
- 都属于实时调度策略,优先级范围 1~99。
- 都遵循高优先级抢占低优先级的原则。
- 都优先于普通任务(SCHED_OTHER)运行。
不同点:
- 调度方式:SCHED_FIFO 是先进先出,同优先级不轮转;SCHED_RR 是同优先级时间片轮转。
- 时间片:SCHED_FIFO 没有时间片概念;SCHED_RR 有固定时间片。
- 同优先级行为:SCHED_FIFO 任务会一直运行到阻塞或让出;SCHED_RR 任务时间片用完后会被放到队列尾部。
- 适用场景:SCHED_FIFO 适合对确定性要求极高、任务执行时间短且可控的场景;SCHED_RR 适合多个同优先级实时任务需要公平共享 CPU 的场景。
五、加分项:结合实际场景与陷阱
面试中如果只背概念,很难脱颖而出。以下这些加分点可以帮你拉开差距:
1. 优先级反转与优先级继承
实时系统中经典的问题是优先级反转。当一个高优先级任务等待一个被低优先级任务持有的锁时,如果中间有一个中优先级任务抢占了低优先级任务,就会导致高优先级任务被无限期阻塞。Linux 通过优先级继承(Priority Inheritance)机制来缓解这个问题,但在 SCHED_FIFO 下如果使用不当,风险依然很大。
2. 实时 throttling 机制
从 Linux 3.14 开始,内核引入了实时 throttling 机制。默认情况下,实时任务最多占用 95% 的 CPU 带宽(通过 /proc/sys/kernel/sched_rt_runtime_us 和 sched_rt_period_us 控制)。这是为了防止实时任务把系统跑死。面试时提到这个,说明你关注的是较新的内核行为。
3. 如何设置实时优先级
在实际操作中,可以通过以下方式设置:
- 使用 chrt 命令:
chrt -f 50 ./my_program(FIFO)或chrt -r 50 ./my_program(RR)。 - 在代码中使用 pthread_setschedparam() 或 sched_setscheduler()。
- 需要注意权限问题:普通用户通常无法设置实时优先级,需要 CAP_SYS_NICE 能力或 root 权限。
4. 常见误区
- 误区一:认为 SCHED_RR 一定比 SCHED_FIFO 好。实际上,如果只有一个关键实时任务,FIFO 反而更简单、开销更小。
- 误区二:认为实时任务优先级越高越好。过高的优先级加上死循环,会导致系统完全不可用。
- 误区三:忽略普通任务的饥饿问题。实时任务长期占用 CPU 会导致普通任务得不到调度,影响系统整体功能。
六、总结:面试回答的黄金模板
最后,给你一个可以直接套用的回答模板:
“SCHED_FIFO 和 SCHED_RR 都是 Linux 的实时调度策略,优先级范围都是 1 到 99,都优先于普通任务运行,也都遵循高优先级抢占低优先级的原则。它们的核心区别在于同优先级任务之间的调度行为:SCHED_FIFO 是先进先出,同优先级任务不会互相抢占,一个任务会一直运行到主动阻塞、让出或被更高优先级任务抢占;而 SCHED_RR 在此基础上引入了时间片,同优先级任务在时间片用完后会轮转到队列尾部,实现公平共享。在实际使用中,SCHED_FIFO 适合单个或少量确定性要求极高的任务,SCHED_RR 适合多个同优先级任务需要公平调度的场景。同时需要注意实时 throttling 机制和优先级反转问题,避免实时任务导致系统饥饿。”
这样的回答既有概念对比,又有实践认知,还有风险意识,基本可以覆盖面试官对这个问题的所有期待。
未经允许不得转载:任鹏个人博客 » Linux 面试中如何回答实时调度策略 SCHED_FIFO 与 SCHED_RR

