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

如何用 ps 和 top 看清进程的真实优先级?
ps 和 top 显示的 “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进入字段管理,启用CLS和RTPRIO列,否则你会误以为所有进程都走 CFS - 常见错觉:看到某个进程
NI = -5就以为它“很优先”,但如果它是cls=TS且没设rtprio,那它和NI = 0的进程在 CFS 下竞争 CPU 的权重其实只差一点点——nice 值对响应延迟影响远不如调度类切换来得剧烈
用 chrt 设置实时调度策略时为什么总报 “Operation not permitted”?
这不是权限不够,而是默认情况下非 root 用户无法使用 SCHED_FIFO 或 SCHED_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 ./myproc或chrt -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% —— 因为没有竞争者,权重无从体现
真正难调的从来不是数字本身,而是搞清哪个调度器在管这个进程、它有没有实际竞争、以及你的观测工具是否在看对的字段。










