我正在爲我正在開發的項目組建一個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