使用 pthread_setschedparam 会显示 Htop 中线程的负优先级

using pthread_setschedparam shows negative priorities on threads in htop

本文关键字:线程 优先级 Htop 显示 pthread setschedparam 使用      更新时间:2023-10-16

我在/etc/security/limits.conf 中为 centOS 版本 6.5 内核 3.4.102-1 自定义构建x86_64设置了以下设置

*             -       rtprio          99 

当我为名为 PThreadAffinity 的测试代码运行下面的代码时,下面显示了进程和优先级的线程(向右滚动以查看树(。为什么优先级未按代码中指定的方式显示? 这意味着在 main(( 中分配给下面线程的优先级是 39、1、20 和 2。尽管在 htop 中它们显示为 -3、-21、-2 和 -40。

30009 bjackfly   20   0  303M  1036   864 S  0.0  0.0  0:00.00 │  │        └─ ./PThreadAffinity     
30013 bjackfly   -3   0  303M  1036   864 S  0.0  0.0  0:00.00 │  │           ├─ ./PThreadAffinity  
30012 bjackfly  -21   0  303M  1036   864 S  0.0  0.0  0:00.00 │  │           ├─ ./PThreadAffinity  
30011 bjackfly   -2   0  303M  1036   864 S  0.0  0.0  0:00.00 │  │           ├─ ./PThreadAffinity  
30010 bjackfly  -40   0  303M  1036   864 S  0.0  0.0  0:00.00 │  │           └─ ./PThreadAffinity  

资料来源:

       #include <thread>
       #include <pthread.h>
       #include <sstream>
       #include <cstring>
       #include <iostream>
       #include <stdexcept>
       std::string schedAttrAsStr(const int aPolicy, const sched_param &aParam) {
           std::stringstream ss;
           ss << ((aPolicy == SCHED_FIFO)  ? "SCHED_FIFO" :
                   (aPolicy == SCHED_RR)    ? "SCHED_RR" :
                   (aPolicy == SCHED_OTHER) ? "SCHED_OTHER" :
                   "???")
               << " @ " << aParam.sched_priority;
           return ss.str();
       }
       void createManaged(std::string aName, int aCpuNum, int aPriority, int aPolicy) { 
           cpu_set_t cpus;
           CPU_ZERO(&cpus);
           CPU_SET(aCpuNum, &cpus);
           int err;
           if((err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpus)) != 0)  {
               std::ostringstream os;
               os << "ERROR: Could not set affinity for cpu " << aCpuNum << "n";
               std::cout << os.str() << std::endl;
           }
           // check if we have an exsiting schedule parameter
           sched_param oldParam;
           int oldPolicy;
           if(pthread_getschedparam(pthread_self(), &oldPolicy, &oldParam) == 0) {
               std::ostringstream os;
               os << "Threader old param for " << aName << " is " << schedAttrAsStr(oldPolicy, oldParam) << "n"; 
           }

           sched_param param;
           memset(&param,0,sizeof(param));
           param.sched_priority = aPriority;
           if (aPriority > sched_get_priority_max(aPolicy)  || aPriority < sched_get_priority_min(aPolicy) ) { 
               std::ostringstream os;
               os << "Priority: " << aPriority << " is out of range for Policy: " << schedAttrAsStr(aPolicy, param)  << "n";
               std::cout << os.str() << std::endl;
               throw std::runtime_error(os.str().c_str());
           }
           int ret = pthread_setschedparam(pthread_self(), aPolicy, &param);
           if(ret != 0) { 
               std::ostringstream os;
               std::cout << " Failed to set scheduler parameters for: " << aName << "n";
               os << os.str() << std::endl;
               throw std::runtime_error(os.str().c_str());
           }
           else 
           {
               std::ostringstream os;
               os  << "Threader successfully set scheduler parameters for " << aName << " thread to " << schedAttrAsStr(aPolicy, param) <<
   "n";
               std::cout << os.str() << std::endl;;
           }
           // Verify new
           if(pthread_getschedparam(pthread_self(), &oldPolicy, &oldParam) == 0)  { 
               std::ostringstream os;
               os << "Threader new param for " << aName << " is " << schedAttrAsStr(oldPolicy, oldParam) << "n";
               std::cout << os.str() << std::endl;
           }
           else { 
               std::ostringstream os;
               os << " Threader Failed to get new parameters for: " << aName << "n";
               std::cout << os.str() << std::endl;
           }
       };
       void runData(int aThreshold, std::string aName, int aCpuNum, int aPriority, int aPolicy) { 
           createManaged(aName,aCpuNum,aPriority,aPolicy);
           std::chrono::milliseconds timespan(aThreshold);      
           std::this_thread::sleep_for(timespan);
           std::ostringstream os;
           os << "Done Processing ThreadID: " << std::this_thread::get_id() << "n";
           std::cout << os.str() << std::endl;
       }
       int main() { 
           std::thread thr1(runData,900000,"Thread1",1,39,SCHED_FIFO);
           std::thread thr2(runData,900000,"Thread2",2,1,SCHED_FIFO);
           std::thread thr3(runData,900000,"Thread3",3,20,SCHED_FIFO);
           std::thread thr4(runData,900000,"Thread4",4,2,SCHED_FIFO);
           thr1.join();
           thr2.join();
           thr3.join();
           thr4.join();
       }

tl;dr - procfs 将实时优先级报告为 1- prio ,但您的代码实际上工作正常。

这主要是因为/proc文件系统的复杂性。

首先,您的优先级向后映射(查看 htop 输出中的进程 ID(。实际映射如下:

Thread1: Prio 39, reported -40
Thread2: Prio 1 , reported -2
Thread3: Prio 20, reported -21
Thread4: Prio 2 , reported -3

htop从每个进程procfs条目下名为stat的文件获取其信息,例如,您的线程信息将从/proc/30010/stat读取。在procfs手册页中如下:

/

proc/[pid]/stat 有关进程的状态信息。这是由 ps(1( 使用的。它在/usr/src/linux/fs/proc/array.c 中定义。

(18( (Linux 2.6 的解释(对于运行实时调度策略(下面的策略;请参阅sched_setscheduler(2((的进程,这是否定的调度优先级减去 1;也就是说,一个介于 -2 到 -100 之间的数字,对应于实时优先级 1 到 99。对于在非实时调度策略下运行的进程,这是内核中表示的原始 nice 值 (setpriority(2((。内核将 nice 值存储为 0(高(到 39(低(范围内的数字,对应于用户可见的 nice 范围 -20 到 19。