【问题标题】:How to check for permissions for sched_setscheduler()?如何检查 sched_setscheduler() 的权限?
【发布时间】:2013-12-05 22:43:17
【问题描述】:

我有一个调用 sched_setscheduler(pid, SCHED_RR, ... ) 的 C++ 应用程序。

应用程序在具有 root 权限的 Linux 上运行。并且通话通常有效。仅在一个特定的虚拟专用服务器中失败并显示EPERM

有没有人遇到过具有 root 权限的进程无法执行此操作的情况?

如何检查进程是否拥有所有必要的权限以避免调用?

更新: 我发现它唯一的基于 Virtuozzo 的虚拟服务器会发生这种情况。使用例如的虚拟机。 KVM 没问题。

【问题讨论】:

    标签: c++ linux permissions scheduler vps


    【解决方案1】:

    不确定您运行的是哪个内核,但此问题已在here 中讨论。它的修复是here。问题在于CONFIG_SCHED_AUTOGROUP;它不支持SCHED_RRSCHED_FIFO。但是,如果您像我一样,这可能仍然无法解决您的问题。问题在于kernel/sched/core.c(早期内核中的kernel/sched.c)中的这段代码(这个3.4.47代码包含上面的补丁):

    /*
     * 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;
    }
    

    在我的情况下,一个系统工作,一个系统不工作,基于!task_group_is_autogroup(task_group(p)) 子句(两个系统都运行完全相同的内核)。在失败的系统中,此子句的计算结果为 1(即它不在自动组中)。该补丁早在 3.1.10 内核中就出现了。听起来您遇到了与我相同的问题,因为您的系统中只有一个出现故障。这表明存在配置问题。我没有发现/proc/sys/kernel/sched_autogroup_enabled 解决了问题;我在启用自动组的情况下遇到了上述问题,当我禁用它时,另一个问题(rt_runtime 在一个系统上为零,在另一个系统上为 950000000),即使/sys/fs/cgroup/cpu,cpuacct/cpu.rt_runtime_us(我相信这是一个直接链接,或者至少与rt_runtime) 相关,在这两种情况下都表示 950000000。

    所以它看起来就像一个任务被分配给自动组并且成功,而一个任务没有并且因为它没有运行时而失败。

    更新:

    我确实找到了我在https://unix.stackexchange.com/questions/115114/why-are-cgroups-mapped-differently-on-these-two-systems-by-systemd 中讨论的解决方法。如果我更改进程的 cgroup 映射使其位于根 cgroup 中,则可以解决问题。这可以通过将/etc/systemd/system.conf 中的DefaultController 设置为null 来永久更改。

    【讨论】:

      【解决方案2】:

      您是否尝试更改应用程序本身或系统中其他进程的优先级?

      手册页man 2 sched_setscheduler权限和资源限制部分中说,只有拥有CAP_SYS_NICE能力的进程才能将调度策略更改为实时。至少在 2.6.12 之前的内核中,它在较新的内核中变得更加复杂。

      也许给你带来麻烦的机器有一些关于功能或其他东西的特殊配置。

      我认为要检测这种情况,您可以简单地继续执行您已经执行的操作:调用 sched_setscheduler,如果它返回 EPERM,那么,没有权限。

      【讨论】:

      • 这发生在比 2.6.12 更新的内核上。但是我将如何检查 CAP_SYS_NICE 呢?对 sched_setscheduler() 的调用实际上发生在库的深处,所以我想检查是调用该库还是跳过它。
      • 有像captestsetcap 这样的用户空间程序来处理功能。还有capgetcapset 系统调用(参见man 2 capget)。关于你的检查:作为最后的手段,你仍然可以在进入你的图书馆之前尝试 sched_setscheduler 但这可能会暂时改变你的优先级......我建议你查阅 sched_setscheduler 和功能的命名手册页并尝试推断什么是EPERM 的原因。
      • 如果您真的想深入了解这一点,您甚至可能需要查看实现 sched_setscheduler 调用的相关内核版本的 Linux 内核源代码,以查看 EPERM 在什么条件下返回。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 2017-04-07
      • 1970-01-01
      • 2017-09-26
      • 2013-10-21
      • 2016-07-22
      • 2012-06-04
      相关资源
      最近更新 更多