我试图在 Linux 系统上以 SCHED_FIFO 或 SCHED_RR 策略作为 root 生成线程,但我对 pthread_create() 的调用返回 1 (EPERM)。 pthread_create() 的手册页指出,EPERM 指示“调用者没有适当的权限来设置所需的调度参数或调度策略”。 root 不应该能够指定 SCHED_FIFO 或 SCHED_RR 吗?
我已经将创建线程的代码剥离到一个仅执行此操作的小程序中。它对我来说看起来是正确的,但仍然出现错误。我做错了什么?
节目:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static void *_Thread(void *arg)
{
(void)arg;
printf("Thread running!\n");
return NULL;
}
int main(void)
{
int retVal;
pthread_attr_t attr;
struct sched_param schedParam;
pthread_t thread;
retVal = pthread_attr_init(&attr);
if (retVal)
{
fprintf(stderr, "pthread_attr_init error %d\n", retVal);
exit(1);
}
retVal = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
if (retVal)
{
fprintf(stderr, "pthread_attr_setinheritsched error %d\n", retVal);
exit(1);
}
retVal = pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
if (retVal)
{
fprintf(stderr, "pthread_attr_setschedpolicy error %d\n", retVal);
exit(1);
}
schedParam.sched_priority = 1;
retVal = pthread_attr_setschedparam(&attr, &schedParam);
if (retVal)
{
fprintf(stderr, "pthread_attr_setschedparam error %d\n", retVal);
exit(1);
}
retVal = pthread_create(&thread,
&attr,
_Thread,
NULL);
if (retVal)
{
fprintf(stderr, "pthread_create error %d\n", retVal);
exit(1);
}
retVal = pthread_join(thread, NULL);
if (retVal)
{
fprintf(stderr, "pthread_join error %d\n", retVal);
exit(1);
}
printf("main run successfully\n");
return 0;
}
该程序已编译并以 root 身份运行。运行时,它在调用 pthread_create 时程序失败,返回 EPERM。
将线程更改为 SCHED_RR 调度没有任何效果 - EPERM 仍由 pthread_create 返回。
将线程改为SCHED_OTHER调度,并将其优先级改为0,程序就可以正常运行了。
一定是你的实时优先级软限制太严格了。
在运行代码之前在 shell 中调用
ulimit -r unlimited
。或者直接在代码中调用 setrlimit(RLIMIT_RTPRIO, ...)
。
系统范围的限制在
/etc/security/limits.conf
中设置。
令人惊讶的是,差不多10年后我遇到了与OP相同的问题:CentOS 7.6,生成一个实时线程,root用户,ulimit -r说“无限制”,但线程创建失败返回EPERM。原来失败是由Linux内核中的以下子句引起的:
kernel/sched/core.c
if (user) {
#ifdef CONFIG_RT_GROUP_SCHED
/*
* Do not allow realtime tasks into groups that have
no runtime
* assigned.
*/
if (rt_bandwidth_enabled() && rt_policy(policy) &&
task_group(p)->rt_bandwidth.rt_runtime == 0 &&
!task_group_is_autogroup(task_group(p))) {
task_rq_unlock(rq, p, &flags);
return -EPERM;
}
#endif
鉴于此,Linux cgroup 文档 https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt 和 CONFIG_RT_GROUP_SCHED 文档 https://www.kernel.org/doc/Documentation/ Scheduler/sched-rt-group.txt,通过将当前 shell 添加到现有的带有实时调度信息的 cgroup 来解决问题:
cd /sys/fs/cgroup/cpu
echo $$ > tasks
然后运行可执行文件,从当前 shell 生成实时线程,线程创建成功。
我已经在 Linux(2.6 内核)、Solaris 9 和 10 上测试了您的代码。没有问题。这与您的实时优先级设置有关。您可以通过以下方式更改:
ulimit -r unlimited
哎呀。马克西姆已经带着答案来了......
以 root 用户身份运行程序。因为我们搞乱了调度(针对 FIFO 和 RR)。你也(暗示)搞乱了相对优先级,而只有 root 才能做到。
正常运行上面的程序,pthread_create()返回EPERM,但作为root用户可以正常工作。
有关更多信息,请访问:http://www.linuxforums.org/forum/programming-scripting/111359-pthread-error.html
在 CentOS 7 上遇到过这个。将 /proc/sys/kernel/sched_rt_runtime_us 设置为 -1 后,就可以了。