3

我正在为我正在处理的项目组合一个 Unix/Linux 半便携式线程类(即使用 pthread 库)。部分项目需要能够设置某些线程的优先级,以允许同一进程中的其他线程有更多的 CPU 时间;这就是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,main,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在某些环境下设置线程的优先级,还是该功能留给所述环境?

我在这个问题上陷入了僵局,并希望在正确的方向上提供任何见解或指示。

谢谢,如果我的代码/解释不清楚,请告诉我。

4

1 回答 1

2

如果它有助于增加理解,请参考此内容。但是我学到的一点是,SCHED_OTHER 是唯一意味着所有非实时线程都将具有相同的优先级。但是在提到的问题中,即使在 SCHED_OTHER 的情况下,BSD 也给出了 max 和 min 0 和 99,不明白为什么,但有一点很清楚,它不是一个非常便携的,并且依赖它的确切值将无济于事。在这种情况下,进行特殊处理会做得更好,例如如果范围为 [0-0],则使用 nice(如果线程优先级可以通过 nice 固定,请告诉我)用于设置优先级。

谢谢

于 2012-05-22T01:25:43.963 回答