最直接查看线程调度策略和优先级的方法是用 chrt -p [tid],它读取 /proc/[tid]/status 中的 policy 和 rt_priority 字段;需先用 ps -T -p [pid] 获取目标线程 ID(SPID),再执行 chrt -p。

用 chrt -p 查看线程的调度策略和优先级
最直接、无需改代码的方法就是用 chrt 命令查运行中的线程。它本质是读取 /proc/[tid]/status 中的 policy 和 rt_priority 字段,结果可靠且实时。
注意:这里的 tid 是线程 ID(不是 pthread_t),需先用 ps -T -p [pid] 列出所有线程:
ps -T -p 12345 | grep -v SPID # 输出示例: # PID SPID TTY TIME CMD # 12345 12346 ? 00:00:01 myapp # 12345 12347 ? 00:00:02 myapp ← 这个 SPID 就是目标线程 ID
再对具体线程执行:
chrt -p 12347 # 输出示例: # pid 12347's current scheduling policy: SCHED_FIFO # pid 12347's current scheduling priority: 50
-
chrt -p只能查已启动的线程,无法在创建前预览属性 - 若提示
Operation not permitted,说明该线程用了实时策略但当前用户无权限读取(常见于SCHED_FIFO线程被降权后残留) - 对主线程(
SPID == PID)同样适用,无需特殊处理
在 C++ 代码中用 pthread_getschedparam 获取当前线程策略
如果需要在运行时动态检查(比如调试或自适应逻辑),必须用 POSIX API。C++ 标准库 std::thread 不提供调度信息接口,得通过 native_handle() 拿到 pthread_t,再调用底层函数:
立即学习“C++免费学习笔记(深入)”;
struct sched_param param;
int policy;
int ret = pthread_getschedparam(pthread_self(), &policy, ¶m);
if (ret == 0) {
printf("policy=%d, priority=%d\n", policy, param.sched_priority);
}-
pthread_getschedparam第二个参数是输出策略(SCHED_OTHER、SCHED_FIFO等整数常量),不是字符串 - 传
nullptr给第三个参数可只查策略,跳过优先级;但通常一起查更实用 - 该调用不改变线程状态,失败时返回非零值(如
ESRCH表示线程已退出) - 必须链接
-lpthread,否则链接时报undefined reference to pthread_getschedparam
为什么 ps -eo pid,tid,cls,pri,rtprio 显示不准
ps 的 cls(class)列显示的是内核调度类(如 ts 表示 CFS,ff 表示 FIFO),但它把所有实时策略统一映射为 rt,且 rtprio 列只对 SCHED_FIFO/SCHED_RR 有效——对 SCHED_OTHER 线程,该列恒为 -,即使你用 nice 调整过进程优先级。
更关键的是:ps 默认显示的是进程(PID)视角,而线程(TID)的调度策略可能与主线程不同(尤其显式调用过 pthread_setschedparam 的子线程)。所以:
- 别依赖
ps的cls或rtprio判断具体线程策略 - 想确认某线程真实策略,必须结合
ps -T -p [pid]找TID,再用chrt -p [tid] -
ps -eo更适合快速筛查“有没有实时线程”,不适合精确定位
调试时容易忽略的权限和继承问题
Linux 下线程默认继承创建者的调度策略,但有两个隐藏陷阱:
- 普通用户创建的线程,即使代码里设了
SCHED_FIFO,实际生效时会被内核静默降级为SCHED_OTHER(除非进程有CAP_SYS_NICE能力或rlimit调高) - 用
std::thread构造时若未显式设置属性,其pthread_attr_t是默认值,对应SCHED_OTHER+ 优先级 0;但一旦用pthread_create并传入自定义attr,就必须确保pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED),否则策略可能被忽略 - 用
chrt -p查到策略是SCHED_OTHER,不代表没被调整过 nice 值——nice 影响的是 CFS 内部的虚拟运行时间,不改变策略名,需用ps -o pid,tid,nice,cls -T -p [pid]额外确认
真正要定位调度异常,得把 chrt -p [tid]、ps -o pid,tid,nice,cls,rtprio -T -p [pid]、以及代码中 pthread_getschedparam 的输出三者交叉比对——策略名一致只是起点,优先级数值、是否生效、是否被降级,才是关键。


















