普通用户需root权限或CAP_SYS_NICE能力才能设置SCHED_FIFO;线程须处于可调度未终止状态,优先级必须为1–99;设置后须用sched_getscheduler验证,且需避免CPU霸占。

需要 root 权限才能设置 SCHED_FIFO
普通用户进程无法直接将调度策略设为 SCHED_FIFO,系统会返回 EPERM 错误。必须以 root 身份运行,或给二进制文件赋予 CAP_SYS_NICE 能力:
sudo setcap cap_sys_nice+ep ./my_program
否则调用 pthread_setschedparam 会静默失败(返回 0 但实际未生效),或返回非零错误码。验证是否生效,得用 sched_getscheduler 再读一次。
pthread_setschedparam 设置前必须先 detach 或 join 线程
对已启动的线程调用 pthread_setschedparam 是安全的,但常见错误是:在 pthread_create 后立刻设置,却忘了线程可能已开始执行、甚至已退出 —— 这时再设就无效或触发未定义行为。
- 确保线程处于“可调度但尚未终止”状态;更稳妥的做法是在新线程入口函数开头就调用
pthread_setschedparam - 不要在主线程中反复对同一子线程句柄多次设置;
pthread_t句柄不因线程退出而自动失效,但操作已终止线程会 UB - 若线程已
join或detach,不能再对其设置调度参数
设置 SCHED_FIFO 必须指定有效优先级(1–99)
SCHED_FIFO 不接受优先级 0;Linux 要求实时优先级范围是 1 到 99(sysconf(_SC_CHILD_MAX) 无关,别被误导)。值越大,优先级越高,且会抢占所有 SCHED_OTHER 和低优先级实时线程。
立即学习“C++免费学习笔记(深入)”;
示例代码片段(关键部分):
struct sched_param param;
param.sched_priority = 50; // 必须在 1–99 之间
int ret = pthread_setschedparam(thread, SCHED_FIFO, ¶m);
if (ret != 0) {
fprintf(stderr, "pthread_setschedparam failed: %s\n", strerror(ret));
}
// 验证是否成功
int policy = sched_getscheduler(0); // 0 表示当前线程
if (policy != SCHED_FIFO) {
fprintf(stderr, "policy is still %d\n", policy);
}
注意:pthread_setschedparam 成功返回 0,但不保证立即生效——内核会在下一次调度点应用新策略。
实时调度线程容易导致系统无响应
SCHED_FIFO 线程一旦获得 CPU,会一直运行直到主动让出(sleep、read 阻塞)、被更高优先级实时线程抢占,或调用 sched_yield。没写好就极易霸占 CPU:
- 避免在
SCHED_FIFO线程中做无界循环、忙等待或长耗时计算 - 务必设置
rlimit(如setrlimit(RLIMIT_RTTIME, ...))防止硬实时线程失控锁死系统 - 调试时建议先用
SCHED_RR+ 中等优先级测试逻辑,再切到SCHED_FIFO
真实场景中,多数嵌入式或音视频同步需求并不真需要 SCHED_FIFO,SCHED_RR 配合合理优先级和 sleep/yield 更可控。SCHED_FIFO 的“一跑到底”特性,恰恰是最难调试也最容易被忽略的负担。


















