【问题标题】:pthreads with real time priority具有实时优先级的 pthread
【发布时间】:2011-03-13 12:25:59
【问题描述】:

我需要管理一个具有不同优先级的线程池,所以我编写了以下线程启动程序:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    assert(pthread_attr_init(&attr) == 0);
    assert(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0);
    assert(pthread_attr_setschedparam(&attr, &param) == 0);
    err = pthread_create(&thrd->handler, &attr, thread_routine, (void *)thrd);
    pthread_attr_destroy(&attr);

    return err;
}

原则上不应允许非特权用户执行此代码:pthread_create() 调用应返回 EPERM,因为运行具有高优先级的线程会带来安全隐患。

出乎意料的是它适用于普通用户,但它根本不尊重给定的优先级。

我尝试通过删除pthread_attr_t 并在创建线程后设置调度属性来修改代码:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    err = pthread_create(&thrd->handler, NULL /*&attr*/, thread_routine,
                         (void *)thrd);
    if (err != 0) return err;

    err = pthread_setschedparam(thrd->handler, SCHED_FIFO, &param);
    if (err != 0) return err;

    return err;
}

顺便说一句,这种方法更难管理,因为如果出现错误,我需要终止新创建的线程。至少在权限要求方面它似乎可以正常工作(只有 root 可以执行此操作),但仍然不尊重优先级。

我做错了吗?

编辑

我刚刚添加了以下由每个线程执行的代码:

static
void getinfo ()
{
    struct sched_param param;
    int policy;

    sched_getparam(0, &param);
    DEBUG_FMT("Priority of this process: %d", param.sched_priority);

    pthread_getschedparam(pthread_self(), &policy, &param);

    DEBUG_FMT("Priority of the thread: %d, current policy is: %d and should be %d",
              param.sched_priority, policy, SCHED_FIFO);
}

使用第一种方法(即pthread_attr_t 方法)事实证明,pthread_attr_setschedpolicy 完全无效,因为优先级为0,并且策略不是SCHED_FIFO。

使用第二种方法(即pthread_setschedparam 方法),该函数会打印预期的数据,但执行会一直以错误的方式运行。

【问题讨论】:

  • 你如何确定调用不被尊重?我遇到过类似的情况,但 API 根本没有实现,因此失败了。
  • @Ioan:查看问题的更新版本。
  • OT:不要将代码放入assert()。如果这是在禁用断言的情况下编译的,则代码将不会被执行。
  • @bstpierre:真的吗?感谢您提供此信息!我曾经在我的代码中经常这样做,特别是为了检查 malloc() 以返回不为 NULL 的东西!所以似乎是时候对我所有的库进行硬修复了,我欠你一杯啤酒!
  • 如果 NDEBUG 被定义,assert(x) 是一个 noop。

标签: c pthreads real-time scheduling


【解决方案1】:

我认为您还必须使用pthread_attr_setinheritsched 以确保您对优先级设置的更改得到考虑。从手册页:

PTHREAD_INHERIT_SCHED 指定调度策略和相关属性是 从创造中继承 线程和调度属性 在这个 attr 参数中 忽略。

PTHREAD_EXPLICIT_SCHED 指定调度策略和相关属性是 设置为相应的值 来自这个属性对象。

在手册页再往前一点,你有:

新的inherit-scheduler属性的默认设置 初始化的线程属性对象是 PTHREAD_INHERIT_SCHED。

【讨论】:

  • 成功了!非常感谢:这解决了两个问题之一。然而,这有点违反直觉:如果我指定您的优先级,可能是因为我希望您使用它,对吧? :) 现在我将找到错误行为的原因:可能是一个错误?
  • @Dacav:你能详细说明你的第二个问题吗?不知道我明白了。该区域的错误(但您自己的;-)不太可能出现。你没有对你正在运行的系统多说,但现在线程实现每天都经过数十亿次的良好测试。
  • 目前我的程序只是一个脚手架:以后会添加真正的业务逻辑。为了测试优先级,每个线程都从等待一个条件变量开始,该条件变量随后被广播。然后每个线程都在stderr上写假。我期望的是在低优先级线程之前观察高优先级线程的虚假。我怀疑我的双核是造成意外交错的原因……我现在正在考虑一个好的测试。
  • 大声笑,现在我明白了 :)。通过说“可能是一个错误”,我的意思是“可能是一个错误在我的代码中”。我通常认为库代码是正确的。 :)
猜你喜欢
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多