Linux 从 2.6.23 开始使用 CFS(Completely Fair Scheduler). 在 Linux 内核看来, 它不区分进程和线程, 每个都是可调度的 Thread.
每个新创建的 Thread 都有一个 Schedule Policy 属性和一个 Static Priority 属性. CFS 主要根据这2 个属性的值, 确定当前线程是不是能分配 CPU 时间.
Linux 上的 Scheduler Policy 主要有:
- SCHED_OTHER # Linux kernel 里面又名 SCHED_NORMAL
- SCHED_IDLE
- SCHED_BATCH
- SCHED_FIFO #First In First Out 先进先出
- SCHED_RR # Round Robin 是 SCHED_FIFO 的改进版本
以上这些 Policy 又被分为 2 大类(Classes):
- Normal scheduling policies (正常) 包含 SCHED_OTHER, SCHED_IDLE, SCHED_BATCH;
- real-time policies (实时) 包含 SCHED_FIFO, SCHED_RR
对于 Normal scheduling policies 的线程, 它的静态优先级一定是 0, 这个值在scheduler 安排他们在 CPU 上执行决策的时候, 是不考虑的.
对于 Real-time policies 的线程, 它的静态优先级范围是 1(低) ~ 99(高).
从概念上讲(实际并不一定是这么做的, 效果是一样的), 每个优先级都有一个线程列表, 里面都是同优先级的线程. CFS 从高优先级队列到低优先级队列按照顺序去找, 高优先级队列里面执行完了, 再执行第优先级队列. 同一个队列里面从头往后执行.
不同优先级线程之间根据优先级(priority) 去安排, 相同优先级的线程根据 Scheduler Policy 去安排执行顺序和时间;
Linux 默认的线程 Policy 是SCHED_OTHER, 所以这些默认的静态优先级都是 0. 它们都比 Real-time 的线程优先级低. 对于 SCHED_OTHER 队列里面的线程, 因为静态优先级都是0, 所以它们使用动态优先级(dynamic priority) 来决定谁先运行. 动态优先级使用 nice 的值来决定谁先运行. nice 的值决定一个线程在一个时间区间内可以运行的时长, 通常情况下没有 nice 值的线程都有相同的运行时长, 改变 nice 的值, 就能改变在一个时间区间内它能运行的时长.
nice 的值只对 policy 是 SCHED_OTHER & SCHED_BATCH 的线程有效. 在 Linux 上 nice 的值是 per-thread 的. 在当前的 Linux 系统, nice 的值可以是: -20 (high priority) to +19 (low priority). 它意味着你越 nice, 你的优先级越低, 越不 nice (负值), 你的优先级就越高. 当前 Linux 系统里面, nice 的值相差一个单位, 一个时间区间内大概运行时间比原来是 1:1.25.
Policy | Static Priority | Dynamic Priority(nice) |
---|
SCHED_OTHER | 0 | -20 ~ 19 |
SCHED_RR | 0 ~ 99 | N/A |
我们看到上面说 Linux 的 Real-time 的线程优先级是 1(低) ~ 99(高), 而 Normal 的线程优先级是 0, 根据 nice 可以调整的值, Normal 线程可以做到nice 的值 -20 ~ 19, 如果 mapping 的到优先级, 则可以是 0 ~ 39. 这里 0 ~ 39 值越低, 优先级越高. 如果把 Real-time 的优先级都加一个负号, 就变成了 -99(高) ~ 1(低), 那么就可以连起来了. 所有优先级是: -99 ~ 1, 0 ~ 39, 并且值越小, 优先级越高. 所以可以认为 Normal 的优先级默认是 20(本来是 0), 通过 nice 改成了 0(-20) ~ 39 (19). 这样一来, 是不是就跟 top 里面的 prio 和 ni 值匹配了?
普通用户只能使用 nice 的值把进程调的更 nice (0 ~ 20), 不能调的更不 nice (-10 ~ -1). 但是 root 可以.
另外, 当没有 CPU 竞争的时候, 比如系统有 8 个 CPU, 只有 3 个在忙, Priority 基本不起作用.
参考: https://man7.org/linux/man-pages/man7/sched.7.html