【发布时间】: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, ¶m) == 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, ¶m);
if (err != 0) return err;
return err;
}
顺便说一句,这种方法更难管理,因为如果出现错误,我需要终止新创建的线程。至少在权限要求方面它似乎可以正常工作(只有 root 可以执行此操作),但仍然不尊重优先级。
我做错了吗?
编辑
我刚刚添加了以下由每个线程执行的代码:
static
void getinfo ()
{
struct sched_param param;
int policy;
sched_getparam(0, ¶m);
DEBUG_FMT("Priority of this process: %d", param.sched_priority);
pthread_getschedparam(pthread_self(), &policy, ¶m);
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