2012-05-21 60 views
3

我正在为我正在开发的项目组建一个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_FIFOSCHED_RR优先级来得到最小/最大值,它给了我有效的最小/最大值,我没有得到'无效参数'的错误,但函数循环输出不是按优先级顺序排列,而是按函数发生调用的顺序(如果没有设置优先级,则预期)。

理想情况下,我会得到当前进程的优先级,然后分配该类的线程,但是,如果当前进程的优先级是SCHED_OTHER然后设置一个线程根据产生无效结果我不想要。

是否有更多的“便携”方式来设置线程的优先级或获取有效的最小/最大值?我甚至可以在某些环境下根据SCHED_OTHER设置线程的优先级,还是该功能留给所述环境?

我在这个问题上处于僵局,希望能在正确的方向上有所洞察或指点。

谢谢,请让我知道如果我的代码/解释不清楚。

回答

1

如果有助于增进了解,请参阅this。但是,我学到了什么,SCHED_OTHER仅仅意味着所有非实时线程将具有相同的优先级。但是后来在提到BSD的时候给出了max和min 0和99甚至在SCHED_OTHER的情况下,都不明白为什么,但有一点很清楚,它不是一个非常便携的,并且依靠它的确切值不会有帮助。在这种情况下,进行特殊处理会更好,如果范围是[0-0],那么使用nice(如果线程优先级可以通过很好的方式修复,请让我知道)用于设置优先级。

谢谢

+1

感谢您的信息!不幸的是,使用'nice'只对流程而非线程有效,但从我在不同的内核源中可以看到的情况来看,线程优先级依赖于系统; OpenBSD实现绝对最小的POSIX标准,但具有更稳健的线程调度器,而Ubuntu实现了一些不可移植的POSIX习惯用法,并且具有更简单的线程调度器,其中Solaris仅实现SCHED_OTHER策略。我仍然在寻找这个.. – txtechhelp