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

kyks70gy  于 2023-10-16  发布在  Linux
关注(0)|答案(5)|浏览(144)

我尝试以根用户身份在Linux系统上使用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调度没有影响-pthread_create仍然返回EPERM。
将线程更改为SCHED_OTHER调度,并将其优先级更改为0,这样程序就可以无错误地运行。

368yc8dk

368yc8dk1#

一定是你的实时优先软限制太严格了。
在运行代码之前,在shell中调用ulimit -r unlimited。或者直接在代码中调用setrlimit(RLIMIT_RTPRIO, ...)
系统范围的限制以/etc/security/limits.conf为单位设置。

4ioopgfo

4ioopgfo2#

令人惊讶的是,我遇到了与10年后的OP相同的问题:CentOS 7.6,生成一个实时线程,root用户,ulimit -r表示“unlimited”,但线程创建失败,返回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生成一个实时线程,线程创建成功。

flvtvl50

flvtvl503#

我已经在Linux(2.6内核),Solaris 9和10上测试了你的代码。没问题。这与您的实时优先级设置有关。您可以通过以下方式更改此设置:

ulimit -r unlimited

哎呀,马克西姆已经带着答案来了。

bjp0bcyl

bjp0bcyl4#

以root用户身份运行程序。因为我们正在扰乱调度(它的FIFO和RR)。你也会(含蓄地)混淆相对优先级,而这只有root才能做到。
在上面的程序正常运行时,pthread_create()返回EPERM,但作为root用户,它工作得很好。
欲了解更多信息,请访问:http://www.linuxforums.org/forum/programming-scripting/111359-pthread-error.html

5f0d552i

5f0d552i5#

在CentOS 7上遇到了这个。在将/proc/sys/kernel/sched_rt_runtime_us设置为-1之后,它就可以工作了。

相关问题