html tool

显示标签为“cpu”的博文。显示所有博文
显示标签为“cpu”的博文。显示所有博文

2022年11月10日星期四

转:进程优先级,进程nice值和%nice的解释

 https://blog.csdn.net/qq_44222849/article/details/105802672

【popexizhi:这里对NI和%nice 很清晰,赞!

总结一下,优先级是进入cpu前的队列 权限;而Nice是单位时间cpu分片给你的个数,前者是排号先后,后者是可以都给你的资源,维度不一致;优先级是插队,而nice是排队后供应的内容可以多给你的量,你有优先级,是认识管理排队的人,排队前后走后门;而nice可是认识买东西的,买的时候直接多给你啊!!! 不过两者好像都有用,资源有限时,你就是nice在低,排队靠后,当轮到你时就没有可以买给你的了吧?!再想想,这里的资源是时间片,逻辑上应该是没有耗尽的,所以nice一定有用的!:)

用top或者ps命令会输出PRI/PR、NI、%ni/%nice这三种指标值,这些到底是什么东西?先给出大概的解释如下:

PRI :进程优先权,代表这个进程可被执行的优先级,其值越小,优先级就越高,越早被执行

NI :进程Nice值,代表这个进程的优先值

%nice :改变过优先级的进程的占用CPU的百分比 (呵呵,这句好难理解是吧,不急慢慢来_)[popexizhi: 从下面的例子上看,这里可以理解为, 对一个进程单位时间,系统最多可以给你 两个进程的时间片-20,至于你定义多少NI一定在这个范围,而%nice 是你计划多要的/可以多给你的-20 比例 ]

PRI是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。如前面所说,PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。由此看出,PR是根据NICE排序的,规则是NICE越小PR越前(小,优先权更大),即其优先级会变高,则其越快被执行。如果NICE相同则进程uid是root的优先权更大。

在LINUX系统中,Nice值的范围从-20到+19(不同系统的值范围是不一样的),正值表示低优先级,负值表示高优先级,值为零则表示不会调整该进程的优先级。具有最高优先级的程序,其nice值最低,所以在LINUX系统中,值-20使得一项任务变得非常重要;与之相反,如果任务的nice为+19,则表示它是一个高尚的、无私的任务,允许所有其他任务比自己享有宝贵的CPU时间的更大使用份额,这也就是nice的名称的来意。

进程在创建时被赋予不同的优先级值,而如前面所说,nice的值是表示进程优先级值可被修正数据值,因此,每个进程都在其计划执行时被赋予一个nice值,这样系统就可以根据系统的资源以及具体进程的各类资源消耗情况,主动干预进程的优先级值。在通常情况下,子进程会继承父进程的nice值,比如在系统启动的过程中,init进程会被赋予0,其他所有进程继承了这个nice值(因为其他进程都是init的子进程)。

对nice值一个形象比喻,假设在一个CPU轮转中,有2个runnable的进程A和B,如果他们的nice值都为0,假设内核会给他们每人分配1k个cpu时间片。但是假设进程A的为0,但是B的值为-10,那么此时CPU可能分别给A和B分配1k和1.5k的时间片。故可以形象的理解为,nice的值影响了内核分配给进程的cpu时间片的多少,时间片越多的进程,其优先级越高,其优先级值(PRI)越低。%nice,就是改变过优先级的进程的占用CPU的百分比,如上例中就是0.5k/2.5k=1/5=20%。

由此可见,进程nice值和进程优先级不是一个概念,但是进程nice值会影响到进程的优先级变化。

进程的nice值是可以被修改的,修改命令分别是nice和renice。

1、nice命令就是设置一个要执行command进程的nice值,其命令格式是 nice –n adjustment command command_option,如果这里不指定adjustment,则默认为10。

2、renice命令就是设置一个已经在运行的进程的nice值,假设一运行进程本来nice值为0,renice为3后,则这个运行进程的nice值就为3了。

说明:如果用户设置的nice值超过了nice的边界值(LINUX为-20到+19),系统就取nice的边界值作为进程的nice值。

举例如下:

对非root用户,只能将其底下的进程的nice值变大而不能变小。若想变小,得要有相应的权限。

[oracle@perf_dbc ~]$ nice
  • 1

0

[oracle@perf_dbc ~]$ nice -n 3 ls
  • 1

agent bin important_bak logs statistics_import.log TMP_FORUM_STATS.dmp TMP_TAOBAO_STATS.dmp TMP_TBCAT_STATS.dmp top.dmp worksh

[oracle@perf_dbc ~]$ nice -n -3 ls
  • 1

nice: cannot set priority: Permission denied

对root用户,可以给其子进程赋予更小的nice值。

[root@dbbak root]# nice
  • 1

0

[root@dbbak root]# nice -n -3 ls
  • 1

192.168.205.191.txt anaconda-ks.cfg clariion.log Desktop disk1 emc.sh File_sort install.log install.log.syslog log OPS rhel_os_soft root_link_name

同样,renice的执行也必须要有相应的权限方可执行。

2018年10月18日星期四

转: linux线程绑定到指定cpu运行



参考: https://blog.csdn.net/u010383937/article/details/78215325#

[popexizhi: 当前只是指定cpu核号,轮询使用线程,没有加回馈参数]

 测试代码:
[cpp] view plain copy
  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5. #include  
  6.    
  7. #define __USE_GNU  
  8. #include  
  9. #include  
  10. #include  
  11. #include  
  12. #define THREAD_MAX_NUM 100  //1个CPU内的最多进程数  
  13.    
  14. int num=0;  //cpu中核数  
  15. void* threadFun(void* arg)  //arg  传递线程标号(自己定义)  
  16. {  
  17.          cpu_set_t mask;  //CPU核的集合  
  18.          cpu_set_t get;   //获取在集合中的CPU  
  19.          int *a = (int *)arg;   
  20.          printf("the a is:%d\n",*a);  //显示是第几个线程  
  21.          CPU_ZERO(&mask);    //置空  
  22.          CPU_SET(*a,&mask);   //设置亲和力值  
  23.          if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//设置线程CPU亲和力  
  24.          {  
  25.                    printf("warning: could not set CPU affinity, continuing...\n");  
  26.          }  
  27.          while (1)  
  28.          {  
  29.                    CPU_ZERO(&get);  
  30.                    if (sched_getaffinity(0, sizeof(get), &get) == -1)//获取线程CPU亲和力  
  31.                    {  
  32.                             printf("warning: cound not get thread affinity, continuing...\n");  
  33.                    }  
  34.                    int i;  
  35.                    for (i = 0; i < num; i++)  
  36.                    {  
  37.                             if (CPU_ISSET(i, &get))//判断线程与哪个CPU有亲和力  
  38.                             {  
  39.                                      printf("this thread %d is running processor : %d\n", i,i);  
  40.                             }  
  41.                    }  
  42.          }  
  43.    
  44.          return NULL;  
  45. }  
  46.    
  47. int main(int argc, char* argv[])  
  48. {  
  49.          num = sysconf(_SC_NPROCESSORS_CONF);  //获取核数  
  50.          pthread_t thread[THREAD_MAX_NUM];  
  51.          printf("system has %i processor(s). \n", num);  
  52.          int tid[THREAD_MAX_NUM];  
  53.          int i;  
  54.          for(i=0;i
  55.          {  
  56.                    tid[i] = i;  //每个线程必须有个tid[i]  
  57.                    pthread_create(&thread[0],NULL,threadFun,(void*)&tid[i]);  
  58.          }  
  59.          for(i=0; i< num; i++)  
  60.          {  
  61.                    pthread_join(thread[i],NULL);//等待所有的线程结束,线程为死循环所以CTRL+C结束  
  62.          }  
  63.          return 0;  
  64. }  
编译命令:gcc bind.c -o bind -lpthread
执行:./bind
特别注意:
#define __USE_GNU不要写成#define _USE_GNU
#include必须写在#define __USE_GNU之后,否则编译会报错
查看你的线程情况可以在执行时在另一个窗口使用top -H来查看线程的情况,查看各个核上的情况请使用top命令然后按数字“1”来查看。


相关介绍:


CPU亲合力就是指在Linux系统中能够将一个或多个进程绑定到一个或多个处理器上运行.
一个进程的CPU亲合力掩码决定了该进程将在哪个或哪几个CPU上运行.在一个多处理器系统中,设置CPU亲合力的掩码可能会获得更好的性能.

一个CPU的亲合力掩码用一个cpu_set_t结构体来表示一个CPU集合,下面的几个宏分别对这个掩码集进行操作:
   ·CPU_ZERO() 清空一个集合
   ·CPU_SET()与CPU_CLR()分别对将一个给定的CPU号加到一个集合或者从一个集合中去掉.
   ·CPU_ISSET()检查一个CPU号是否在这个集合中.

下面两个函数就是用来设置获取线程CPU亲和力状态: 
    ·sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)       该函数设置进程为pid的这个进程,让它运行在mask所设定的CPU上.如果pid的值为0,则表示指定的是当前进程,使当前进程运行在mask所设定的那些CPU上.第二个参数cpusetsize是mask所指定的数的长度.通常设定为sizeof(cpu_set_t).如果当前pid所指定的进程此时没有运行在mask所指定的任意一个CPU上,则该指定的进程会从其它CPU上迁移到mask的指定的一个CPU上运行. 
    ·sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)       该函数获得pid所指示的进程的CPU位掩码,并将该掩码返回到mask所指向的结构中.即获得指定pid当前可以运行在哪些CPU上.同样,如果pid的值为0.也表示的是当前进程
[cpp] view plain copy
  1. cpu_set_t的定义  
  2.   
  3. # define __CPU_SETSIZE 1024  
  4. # define __NCPUBITS (8 * sizeof (__cpu_mask))  
  5. typedef unsigned long int __cpu_mask;  
  6. # define __CPUELT(cpu) ((cpu) / __NCPUBITS)  
  7. # define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))  
  8. typedef struct  
  9. {  
  10. __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];  
  11. } cpu_set_t;  
  12.   
  13. # define __CPU_ZERO(cpusetp) \  
  14. do { \  
  15. unsigned int __i; \  
  16. cpu_set_t *__arr = (cpusetp); \  
  17. for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i) \  
  18. __arr->__bits[__i] = 0; \  
  19. while (0)  
  20. # define __CPU_SET(cpu, cpusetp) \  
  21. ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu))  
  22. # define __CPU_CLR(cpu, cpusetp) \  
  23. ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu))  
  24. # define __CPU_ISSET(cpu, cpusetp) \  
  25. (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0)