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

时间:2012-02-16 14:52:59

标签: 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;
}

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

将线程更改为SCHED_RR调度无效 - EPERM仍由pthread_create返回。

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

4 个答案:

答案 0 :(得分:4)

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

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

系统范围限制在/etc/security/limits.conf

中设置

答案 1 :(得分:2)

令人惊讶的是,将近 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 产生实时线程的可执行文件,线程创建成功。

答案 2 :(得分:1)

我已经在Linux(2.6内核),Solaris 9和Linux上测试了你的代码。 10.没问题。它与您的实时优先级设置有关。您可以使用以下内容进行更改:

ulimit -r unlimited

糟糕。马克西姆已经得到了答案......

答案 3 :(得分:0)

以root用户身份运行程序。因为我们正在搞乱调度(它用于FIFO和RR)。你也(通过暗示)弄乱了相对优先级,只有root才能这样做。

正常运行程序,pthread_creare()返回EPERM,但是root用户工作正常。

有关详细信息,请访问:http://www.linuxforums.org/forum/programming-scripting/111359-pthread-error.html