2012-05-21 59 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