Linux 线程调度策略
- Linux 线程调度策略包括五种:SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_BATCH 和 SCHED_IDLE。
- 用户空间线程默认使用 SCHED_OTHER 策略。
- 内核空间线程默认使用 SCHED_NORMAL 策略,与 SCHED_OTHER 一致。
- SCHED_OTHER、SCHED_IDLE、SCHED_BATCH 为常规调度策略,不支持线程优先级设置,只能使用默认优先级 0。
- SCHED_FIFO、SCHED_RR 为实时调度策略,支持线程优先级设置,其优先级范围为 1 ~ 99。
SCHED_FIFO
- 先进先出调度,适用于实时任务。
- 只能在静态优先级高于0的情况下使用,这意味着当 SCHED_FIFO 线程变得可运行时,它总是立即抢占当前正在运行的任何 SCHED_OTHER、SCHED_BATCH 或 SCHED_IDLE 线程。
- SCHED_FIFO 线程一直运行到被 I/O 请求阻塞、被高优先级线程抢占或调用 sched_yield 为止。
- SCHED_FIFO 是一种简单的调度算法,没有时间切片。对于 SCHED_FIFO 策略下调度的线程,应用以下规则:
- 被另一个高优先级线程抢占的正在运行的 SCHED_FIFO 线程将保持在其优先级列表的头部,并在所有高优先级线程再次阻塞时立即恢复执行。
- 当阻塞的 SCHED_FIFO 线程变为可运行时,它将被插入到优先级列表的末尾。
SCHED_RR
- 轮询调度,适用于实时任务。
- SCHED_RR 是 SCHED_FIFO 的简单增强。上面为 SCHED_FIFO 描述的所有内容也适用于 SCHED_RR,除了每个线程只允许在最大时间片内运行。
- 如果 SCHED_RR 线程已经运行了等于或大于该时间片的时间段,那么它将被放在优先级列表的末尾。
- 被高优先级线程抢占并随后作为运行线程恢复执行的 SCHED_RR 线程将完成其循环时间量的未过期部分。
SCHED_OTHER
- 默认的 Linux 分时调度,适用于大多数应用程序。
- 能在静态优先级 0 使用(即实时策略下的线程始终比 SCHED_OTHER 进程具有优先级)。
- 标准的 Linux 分时调度器,适用于不需要特殊实时机制的所有线程。要运行的线程选于静态优先级为 0 的列表中动态优先级最高的线程。动态优先级基于 nice 值,并随着线程准备运行但却未被调度的次数而提升优先级。
- nice 值是一个属性,可用于影响 CPU 调度器在调度决策中支持或反对某个进程。在 Linux 上,nice 值是每个线程的属性:同一进程中的不同线程可能有不同的 nice 值。nice值的范围在 Linux 上为 -20(高优先级) 到 +19(低优先级)
SCHED_BATCH
- 批处理调度策略,适用于后台任务。
- 与 SCHED_OTHER 类似,不同之处在于,此策略将导致调度器始终假设线程是 cpu 密集型的。因此,调度程序将对其唤醒行为施加较小的调度损失,从而使该线程在调度决策中受到轻微影响。
- 此策略对于非交互性但不希望降低其 nice 值的工作负载非常有用。
SCHED_IDLE
- 空闲调度策略,以极低的优先级运行作业。
SCHED_FIFO 分析
-
假设在 cpu0 上存在以下3个线程:
线程名 优先级 调度策略 t0 high FIFO t1 high FIFO t2 mid FIFO t3 0 OTHER -
如果 t0 先运行,则 t1 只有在 t0 主动放弃 cpu 时,才会被运行。
-
只要 t0/t1 就绪,就会立刻抢占 t2 和 t3,直到 t0/t1 主动放弃 cpu 为止,t2 或者 t3 才会被运行。
-
只要 t2 就绪,在 t0/t1 已经放弃 cpu 的情况下,其会立刻抢占 t3,直到 t2 主动放弃 cpu 或者被 t0/t1 抢占。
SCHED_RR 分析
-
假设在 cpu0 上存在以下3个线程:
线程名 优先级 调度策略 t0 high RR t1 high RR t2 mid RR t3 0 OTHER -
如果 t0 先运行,则 t1 在 t0 时间片消耗完之后,就能得到运行。
-
虽然存在时间片,但是只要最高优先级的 t0/t1 不主动放弃 cpu,其就会一直得到调度(t0/t1时间片消耗完,发生调度,优先级最高的线程 t0/t1 被选中)。
-
只要 t0/t1 就绪,就会立刻抢占 t2 和 t3,直到 t0/t1 主动放弃 cpu 为止,t2 或者 t3 才会被运行。
-
只要 t2 就绪,在 t0/t1 已经放弃 cpu 的情况下,其会立刻抢占 t3,直到 t2 主动放弃 cpu 或者被 t0/t1 抢占。