Linux 进程优先级与调度策略实战

9次阅读

真实优先级取决于调度策略:普通进程pri=20+ni,实时进程pri=100+rtprio;需用ps -eo pid,comm,ni,pri,cls,rtprio或top启用CLS/RTPRIO列查看,renice对实时进程无效,chrt需先配置ulimit -r或limits.conf。

Linux 进程优先级与调度策略实战

如何用 pstop 看清进程的真实优先级?

pstop 显示的 “PRI”、“NI”、“PR” 容易让人混淆,尤其当调度策略不是默认的 SCHED_OTHER 时。真实优先级(即内核调度器实际使用的值)取决于策略类型,不能只看 NI(nice 值)。

  • ps -eo pid,comm,ni,pri,cls,rtprio 是最实用的组合:其中 cls 显示调度类(如 TS 表示 CFS,FF 表示 SCHED_FIFO),rtprio 对实时进程才有意义,pri 是内核内部的静态优先级(范围 0–139),但注意:对普通进程,pri = 20 + ni;对实时进程,pri = 100 + rtprio
  • top 默认不显示调度策略,按 f 进入字段管理,启用 CLSRTPRIO 列,否则你会误以为所有进程都走 CFS
  • 常见错觉:看到某个进程 NI = -5 就以为它“很优先”,但如果它是 cls=TS 且没设 rtprio,那它和 NI = 0 的进程在 CFS 下竞争 CPU 的权重其实只差一点点——nice 值对响应延迟影响远不如调度类切换来得剧烈

chrt 设置实时调度策略时为什么总报 “Operation not permitted”?

这不是权限不够,而是默认情况下非 root 用户无法使用 SCHED_FIFOSCHED_RR。内核通过 RLIMIT_RTPRIO 限制实时优先级使用,即使你用 sudo 启动程序,若未显式提升该 limit,仍会失败。

  • 检查当前限制:ulimit -r,通常返回 0(表示禁止)
  • 临时提权(需 root):sudo ulimit -r 99 && exec sudo -s 不生效,正确做法是先用 sudo bash,再在该 shell 中运行 ulimit -r 99,然后启动目标进程
  • 更稳妥的方式是修改 /etc/security/limits.conf
  • soft rtprio 99
  • hard rtprio 99

    注意:该配置仅对新登录会话生效,且要求 PAM limits 模块已启用(检查 /etc/pam.d/common-session 是否含 pam_limits.so

renice 对实时进程完全无效?

是的。renice 只修改 NI 字段,而 NI 仅被 CFS(SCHED_OTHER / SCHED_BATCH)读取。一旦进程被 chrt -f 设为 SCHED_FIFO,它的调度行为就彻底脱离 nice 机制。

  • 你执行 renice -20 $(pidof myproc) 后再用 ps -o pid,ni,cls 查看,NI 会变,但 cls 仍是 FF,且调度器完全忽略该 NI
  • 实时进程的“优先级”由 rtprio 决定(范围 1–99),必须用 chrt --fifo 50 ./myprocchrt -p 50 $PID 修改
  • 错误操作示例:chrt -f 10 ./a.out & renice -20 $! —— 后者毫无意义,还可能误导你认为“双重加成”

为什么改了 NI 却看不出 CPU 分配变化?

CFS 不是按“固定时间片”分配 CPU,而是基于 vruntime(虚拟运行时间)做红黑树调度。NI 影响的是进程的“权重”,而非抢占时机或时间片长度。低 nice 值(如 -10)只是让该进程在同等时间内获得约 2.5 倍于 NI=0 进程的 CPU 时间,但前提是:它真正在跑、且有其他可运行进程在竞争。

  • 验证方法:用两个计算密集型进程(如 yes > /dev/NULL &),一个 renice -10,一个保持默认,再用 pidstat -u 1 观察 %CPU 分布,才能看到权重差异
  • 容易忽略的干扰项:I/O 等待、锁竞争、cgroup 限频、CPU affinity(taskset)都会掩盖 nice 效果
  • 最典型的失效场景:单核机器上只有一个 CPU 密集型进程在跑,无论 NI 是多少,它都占满 100% —— 因为没有竞争者,权重无从体现

真正难调的从来不是数字本身,而是搞清哪个调度器在管这个进程、它有没有实际竞争、以及你的观测工具是否在看对的字段。

text=ZqhQzanResources