调用setpriority()修改进程nice值时遇EPERM权限错误求助
问题分析与解决指导
一、核心问题根源
你的问题确实和权限限制直接相关,包括RLIMIT_NICE资源限制以及Linux能力(Capabilities),分两部分拆解:
1. setpriority 报错EPERM的原因
- 普通用户默认仅能提高nice值(范围019,值越大优先级越低),要设置负数nice值(-20-1,优先级更高)需要突破资源限制或获得特殊权限。
- 你之前设置
rl.rlim_cur=20是错误的:RLIMIT_NICE的取值和nice值是反向映射关系,公式为rlim_cur = 20 - nice。比如要允许设置nice=-10,需要rlim_cur=30(20 - (-10) =30),最大值40对应nice=-20。 - sudo执行仍失败,大概率是代码未正确调整
RLIMIT_NICE,或sudo环境下的资源限制未放开。
2. SCHED_RR 实时调度策略失败的原因
SCHED_RR属于实时调度策略,Linux下要求进程必须拥有CAP_SYS_NICE能力才能设置,普通用户默认无此权限,即使sudo也可能因环境限制或权限传递问题失效。
二、分步解决方法
(一)修复setpriority问题
1. 正确设置RLIMIT_NICE
修改代码,在调用setpriority前添加正确的资源限制配置:
struct rlimit rl; // 获取当前RLIMIT_NICE限制 if (getrlimit(RLIMIT_NICE, &rl) == -1) { perror("getrlimit"); exit(EXIT_FAILURE); } // 设置允许nice值低至-10(对应rlim_cur=30) rl.rlim_cur = 30; if (setrlimit(RLIMIT_NICE, &rl) == -1) { perror("setrlimit"); exit(EXIT_FAILURE); }
2. 系统层面放开限制
编辑/etc/security/limits.conf,添加以下配置(替换username为你的用户名):
username soft nice -10 username hard nice -10
保存后重新登录,系统会自动将nice值转换为对应的RLIMIT_NICE值。
3. sudo执行的注意事项
如果sudo仍失败,使用sudo -i进入root shell后再执行程序,避免环境变量或sudoers配置的权限限制影响。
(二)修复SCHED_RR设置问题
要设置实时调度策略,需获得CAP_SYS_NICE权限,两种实现方式:
1. 直接用sudo执行
确保sudo给予完整权限,执行命令:
sudo ./your_program
若仍失败,在/etc/security/limits.conf中添加实时优先级限制:
username soft rtprio 99 username hard rtprio 99
(99是SCHED_RR的最大优先级,对应sched_get_priority_max(SCHED_RR)的返回值)
2. 给程序添加CAP_SYS_NICE能力
无需每次sudo,直接给二进制文件添加永久权限:
sudo setcap cap_sys_nice+ep ./your_program
之后普通用户执行程序即可设置实时调度策略和负数nice值。
三、修改后的完整测试代码
#include <sched.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/time.h> #include <sys/resource.h> int main(void) { int pol; struct sched_param sp; struct rlimit rl; // 先配置RLIMIT_NICE,允许设置nice=-10 if (getrlimit(RLIMIT_NICE, &rl) == -1) { perror("getrlimit"); exit(EXIT_FAILURE); } rl.rlim_cur = 30; if (setrlimit(RLIMIT_NICE, &rl) == -1) { perror("setrlimit"); exit(EXIT_FAILURE); } pol = sched_getscheduler(getpid()); if (pol == -1) { perror("sched_getscheduler"); exit(EXIT_FAILURE); } if (sched_getparam(0, &sp) == -1) { perror("sched_getparam"); exit(EXIT_FAILURE); } printf("%ld: %-5s ", (long)getpid(), (pol == SCHED_OTHER) ? "OTHER" : (pol == SCHED_RR) ? "RR" : (pol == SCHED_FIFO) ? "FIFO" : #ifdef SCHED_BATCH /* Linux-specific */ (pol == SCHED_BATCH) ? "BATCH" : #endif #ifdef SCHED_IDLE /* Linux-specific */ (pol == SCHED_IDLE) ? "IDLE" : #endif "???"); printf("%2d\n", sp.sched_priority); if (setpriority(PRIO_PROCESS, 0, -10) == -1) { perror("setpriority"); exit(EXIT_FAILURE); } printf("New Nice value is %d\n", getpriority(PRIO_PROCESS, 0)); #ifdef _POSIX_PRIORITY_SCHEDULING printf("Setting scheduler to real-time RR and current process priority to %d\n", sched_get_priority_max(SCHED_RR)); sp.sched_priority=sched_get_priority_max(SCHED_RR); printf("sp.sched prio is %d\n", sp.sched_priority); if (sched_setscheduler(getpid(), SCHED_RR, &sp) == -1) { perror("sched_setscheduler"); exit(EXIT_FAILURE); } #endif return 0; }
四、验证步骤
- 编译代码:
gcc -o nice_test nice_test.c - 普通用户测试:先配置
limits.conf并重新登录,或给程序添加CAP_SYS_NICE能力,执行./nice_test - sudo测试:
sudo ./nice_test
内容的提问来源于stack exchange,提问作者Πέτρος Λάμψας
相关产品推荐
相关产品推荐

