【问题标题】:Getting EPERM when calling pthread_create() for SCHED_FIFO thread as root on Linux在 Linux 上以 root 身份为 SCHED_FIFO 线程调用 pthread_create() 时获取 EPERM
【发布时间】:2012-02-16 14:52:59
【问题描述】:

我试图在 Linux 系统上以根用户身份使用 SCHED_FIFO 或 SCHED_RR 策略生成线程,但我对 pthread_create() 的调用返回 1 (EPERM)。 pthread_create() 的手册页说 EPERM 表明“[t]他的调用者没有适当的权限来设置所需的调度参数或调度策略。” 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允许程序无错误地运行。

【问题讨论】:

  • 我相信您需要为调用用户设置CAP_SYS_NICE 功能。我不太了解它如何与sudo 等一起使用。请查看man 7 capabilities
  • 您可以使用ulimit -e 设置nice 级别,方法与设置实时优先级限制相同。它没有为我提供“尤里卡!”不过,现在还来得及。
  • 我们在工作中使用的 Linux 系统是虚拟化服务器。我在这里抓住了救命稻草,但这可能对设置实时优先级有任何影响吗?
  • 在 /etc/security/limits.conf 中查找“rtprio”条目。这大概就是问题所在。就这样的事情而言,虚拟服务器通常设置为完全独立的。您是否有完整的本地根文件系统(未继承)?
  • /etc/security/limits.conf 中对“rtprio”的唯一引用是在注释中。我发现有人在笔记本电脑上运行 Linux(Ubuntu),我让他编译并运行上面的程序,它对他有用,所以这与我们的 Linux 服务器有关,导致了这个问题。我会在我们的 IT 人员明天进来时与他核实一下他们的根文件系统的性质。

标签: c pthreads


【解决方案1】:

一定是你的实时优先级软限制太严格了。

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

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

【讨论】:

  • 调用ulimit -r 确实表明root 的实时优先级限制为0。我首先使用ulimit -r unlimited 更改了它,然后在我的程序中使用setrlimit(...) 但我可以验证限制已更改,我仍然有 EPERM。
  • 您是否处于特殊环境中,可能像 ARM? uname -a 显示什么?
  • uname -a 给了我Linux cumanta 2.6.32-042stab044.17 #1 SMP Fri Jan 13 12:53:58 MSK 2012 i686 i686 i386 GNU/Linux。机器运行 CentOS 6.2。
  • 我在 Fedora 14 上运行了您的代码并成功完成。但是,我的/etc/security/limits.conf 中有自定义设置:@wheel hard rtprio unlimited@wheel soft rtprio 10,我的用户属于wheel 组。
  • 我还在 CentOS 6.2 Linux 2.6.32-220.2.1.el6.x86_64 #1 SMP Tue Dec 13 16:21:34 EST 2011 x86_64 x86_64 x86_64 GNU/Linux 上运行了您的代码,默认为 /etc/security/limits.conf。它在我的非特权用户下失败,并在以root 运行时成功,正如预期的那样。
【解决方案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 生成一个实时线程,线程创建成功。

【讨论】:

  • 哇!我完全击中了同样的东西。伙计……就在我以为我已经看到了那里所有超级不起眼的路障时!感谢您跟踪它!
【解决方案3】:

我已经在 Linux(2.6 内核)、Solaris 9 和 10 上测试了您的代码。没有问题。它与您的实时优先级设置有关。你可以改变它:

ulimit -r unlimited

哎呀。马克西姆已经给出了答案......

【讨论】:

    【解决方案4】:

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

    以上程序正常运行,pthread_create()返回EPERM,但root用户运行正常。

    欲了解更多信息,请访问:http://www.linuxforums.org/forum/programming-scripting/111359-pthread-error.html

    【讨论】:

      猜你喜欢
      • 2022-01-21
      • 1970-01-01
      • 2016-04-11
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-25
      相关资源
      最近更新 更多