在Linux上以root用户身份调用SCHED_FIFO线程的pthread_create()时获取EPERM

Chr*_*isL 5 c pthreads

我试图在Linux系统上以root身份生成带有SCHED_FIFO或SCHED_RR策略的线程,但是我对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;
}
Run Code Online (Sandbox Code Playgroud)

该程序已编译并以root身份运行.运行时,程序在调用pthread_create时失败,返回EPERM.

将线程更改为SCHED_RR调度没有任何效果 - 仍然由pthread_create返回EPERM.

将线程更改为SCHED_OTHER调度并将其优先级更改为0允许程序无错误地运行.

gla*_*lig 9

令人惊讶的是,差不多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
Run Code Online (Sandbox Code Playgroud)

鉴于此,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
Run Code Online (Sandbox Code Playgroud)

然后运行从当前 shell 生成实时线程的可执行文件,线程创建成功。


Max*_*kin 5

一定是您的实时优先级软限制过于严格。

ulimit -r unlimited在运行代码之前,请先在shell中调用。或setrlimit(RLIMIT_RTPRIO, ...)直接在您的代码中调用。

系统范围的限制在中设置/etc/security/limits.conf