我正在为我正在开发的项目组建一个Unix/Linux半可移植线程类(即使用pthread库)。部分项目需要设置某些线程的优先级,以允许同一进程中的其他线程的CPU时间更多;这就是pthread_setschedparam
函数进来的地方,我的班级撞上了一堵砖墙。带SCHED_OTHER的便携式pthread_setschedparam
下面是一个简单的测试,我放在一起,说明我的问题:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
#include <string.h>
#include <errno.h>
pthread_mutex_t m_mtx;
bool m_goahead;
void dosleep(int millis)
{
usleep(millis*1000);
}
void domsg(const char *msg)
{
pthread_mutex_lock(&m_mtx);
std::cout << msg << std::endl;
pthread_mutex_unlock(&m_mtx);
}
void dowait() {
while (!m_goahead) {
dosleep(1);
}
}
void *fn1(void *param)
{
domsg("in fn1...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn1 loop");
}
}
void *fn2(void *param)
{
domsg("in fn2...waiting");
dowait();
while (m_goahead) {
dosleep(1000);
domsg("in fn2 loop");
}
}
int main(int argc, char **argv)
{
// min prio = -2, max prio = 2
int t1_pri = 2, t2_pri = 0, main_pri = 1;
//SCHED_RR, SCHED_FIFO, SCHED_OTHER (POSIX scheduling policies)
int sched = SCHED_OTHER; // standard
// get the range between min and max and set the priorities base on split range
int min = sched_get_priority_min(sched);
int max = sched_get_priority_max(sched);
int skip = (max - min)/5; // 5 since -2...2
struct sched_param main_param, t1_param, t2_param;
memset(&main_param, 0, sizeof(sched_param));
memset(&t1_param, 0, sizeof(sched_param));
memset(&t2_param, 0, sizeof(sched_param));
main_param.sched_priority = (min + ((main_pri+2) * (skip+1))) + (skip/2);
t1_param.sched_priority = (min + ((t1_pri+2) * (skip+1))) + (skip/2);
t2_param.sched_priority = (min + ((t2_pri+2) * (skip+1))) + (skip/2);
std::cout << "main thread will have a prio of " << main_param.sched_priority << std::endl;
std::cout << "t1 thread will have a prio of " << t1_param.sched_priority << std::endl;
std::cout << "t2 thread will have a prio of " << t2_param.sched_priority << std::endl;
m_goahead = false;
pthread_mutex_init(&m_mtx, NULL);
pthread_t t1, t2;
// Create the threads
if (pthread_create(&t1, NULL, fn1, NULL) != 0) {
std::cout << "couldn't create t1" << std::endl;
return -1;
}
if (pthread_create(&t2, NULL, fn2, NULL) != 0) {
std::cout << "couldn't create t2" << std::endl;
return -1;
}
dosleep(1000); // sleep a second before setting priorities
// --main thread--
if (pthread_setschedparam(pthread_self(), sched, &main_param) != 0) {
std::cout << "error setting priority for main thread: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t1 thread--
if (pthread_setschedparam(t1, sched, &t1_param) != 0) {
std::cout << "error setting priority for T1: (" << errno << "), " << strerror(errno) << std::endl;
}
// --t2 thread--
if (pthread_setschedparam(t2, sched, &t2_param) != 0) {
std::cout << "error setting priority for T2: (" << errno << "), " << strerror(errno) << std::endl;
}
m_goahead = true; // all start
// loop until user interupt
for (;;) {
dosleep(1000);
domsg("in main loop");
}
pthread_mutex_destroy(&m_mtx);
return 0;
}
在此基础上的代码,如果我编译这和OpenBSD的系统上运行它,我得到如下:
main thread will have a prio of 24
t1 thread will have a prio of 31
t2 thread will have a prio of 17
in fn1...waiting
in fn2...waiting
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
说明它是如何在线程的优先级顺序,FN1,主,FN2 ...
如果我运行一个Ubuntu 10.04LTS系统上此相同的测试,我得到以下几点:
main thread will have a prio of 3
t1 thread will have a prio of 4
t2 thread will have a prio of 2
in fn1...waiting
in fn2...waiting
error setting priority for main thread: (22), Invalid argument
error setting priority for T1: (22), Invalid argument
error setting priority for T2: (22), Invalid argument
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
in main loop
in fn2 loop
in fn1 loop
我的理解是无效的说法是,因为我指定SCHED_OTHER
优先级,并试图给它分配任何数量的其他比0;我无法确定的是我该如何正确地完成这项工作?
我试着'假设'SCHED_FIFO
或SCHED_RR
优先级来得到最小/最大值,它给了我有效的最小/最大值,我没有得到'无效参数'的错误,但函数循环输出不是按优先级顺序排列,而是按函数发生调用的顺序(如果没有设置优先级,则预期)。
理想情况下,我会得到当前进程的优先级,然后分配该类的线程,但是,如果当前进程的优先级是SCHED_OTHER
然后设置一个线程根据产生无效结果我不想要。
是否有更多的“便携”方式来设置线程的优先级或获取有效的最小/最大值?我甚至可以在某些环境下根据SCHED_OTHER
设置线程的优先级,还是该功能留给所述环境?
我在这个问题上处于僵局,希望能在正确的方向上有所洞察或指点。
谢谢,请让我知道如果我的代码/解释不清楚。
感谢您的信息!不幸的是,使用'nice'只对流程而非线程有效,但从我在不同的内核源中可以看到的情况来看,线程优先级依赖于系统; OpenBSD实现绝对最小的POSIX标准,但具有更稳健的线程调度器,而Ubuntu实现了一些不可移植的POSIX习惯用法,并且具有更简单的线程调度器,其中Solaris仅实现SCHED_OTHER策略。我仍然在寻找这个.. – txtechhelp