C++ 可移植的pthread_setschedparam与SCHED_OTHER

C++ 可移植的pthread_setschedparam与SCHED_OTHER,c++,linux,multithreading,unix,pthreads,C++,Linux,Multithreading,Unix,Pthreads,我正在为我正在进行的一个项目准备一个Unix/Linux半可移植线程类(即使用pthread库)。项目的一部分要求能够设置某些线程的优先级,以允许同一进程中的其他线程有更多的CPU时间;这就是pthread_setschedparam函数出现的地方,我的类遇到了麻烦 下面是一个简单的测试来说明我的问题: #include <iostream> #include <unistd.h> #include <pthread.h> #include <sched

我正在为我正在进行的一个项目准备一个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;
}
请注意它是如何按照线程优先级fn1、main、fn2

如果我在Ubuntu 10.04LTS系统上运行相同的测试,我会得到以下结果:

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
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
优先级类来获取最小值/最大值,这给了我有效的最小值/最大值,我没有得到“invalid argument”错误,但是函数循环输出不是按优先级顺序的,而是按函数调用的顺序(如果未设置优先级,则为预期)

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

有没有更“可移植”的方法来设置线程的优先级或获取有效的最小/最大值?在某些环境中,我甚至可以在
SCHED_OTHER
下设置线程的优先级,还是将该功能留给所述环境

我在这个问题上陷入僵局,希望能有任何正确方向的见解或指点

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

如果有助于提高理解,请参考。但我学到的一点是,SCHED_OTHER是他们唯一的意思,即所有非实时线程将具有同等的优先级。但是在问题中,BSD给出最大和最小值0和99,即使是SCHED_OTHER,我也不理解为什么,但有一点是清楚的,它不是一个非常可移植的,依赖于它的精确值也没有帮助。在这种情况下,使用特殊处理会更好,比如如果范围是[0-0],那么使用nice(如果nice可以固定线程优先级,请让我知道)来设置优先级


感谢

感谢您提供的信息!不幸的是,使用
nice
只对进程有效,而对线程无效,但从我在不同内核源代码中看到的情况来看,线程优先级非常依赖于系统;OpenBSD实现了绝对最小的POSIX标准,但有一个更健壮的线程调度程序,而Ubuntu实现了一些非por的线程调度程序table POSIX习惯用法并且有一个更简单的线程调度程序,其中Solaris只实现了
SCHED_OTHER
策略。。