进程/线程绑定cpu方法探究

1、使用taskset指令

1)获取进程pid

[root@CENTOS57 eq]# ps aux | grep led
root       9240  0.0  0.0   6324   376 pts/0    S    07:40   0:00 ./ledThread
root       9242  0.0  0.0 112660   968 pts/0    S+   07:40   0:00 grep --color=auto led

2)查看进程当前运行在哪个cpu核上

p参数查看进程的绑定cpu核。

[root@CENTOS57 eq]# taskset -p 9240
pid 9240's current affinity mask: 2

显示的十进制数字2转换为2进制为10,每个1对应一个cpu,所以进程运行在第2个cpu核上。

3)指定进程运行在cpu3核上

pc参数绑定cpu核。

[root@CENTOS57 eq]# taskset -pc 3 9240
pid 9240's current affinity list: 2
pid 9240's new affinity list: 3

[root@CENTOS57 eq]# taskset -p 9240
pid 9240's current affinity mask: 8

cpu的标号是从0开始的,所以cpu3表示第4个cpu(第一个cpu的标号是0)。

至此,就把应用程序绑定到了cpu3上运行

4)启动程序时绑定cpu核

#启动时绑定到第二个cpu1
[root@CENTOS57 eq]# taskset -c 1 ./ledall &
[1] 3011

#查看确认绑定情况
[root@CENTOS57 eq]# taskset -p 3011
pid 3011's current affinity mask: 2

2、使用sched_setaffinity系统调用

sched_setaffinity可以将某个进程绑定到一个特定的CPU。

注意:在使用时,需要添加下面宏与头文件,并且顺序不可以颠倒。

#define _GNU_SOURCE    
#include 
cpu_set_t mask;
CPU_ZERO(&mask);    //置空
CPU_SET(n,&mask);   //设置亲和力值,绑定cpu核到(n)核上
/* 设置进程号为pid的进程运行在mask所设定的CPU上
 * 第二个参数cpusetsize是mask所指定的数的长度
 * 通常设定为sizeof(cpu_set_t)
 * 如果pid的值为0,则表示指定的是当前进程 
 */
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
/*
 获得pid所指示的进程的CPU位掩码,并将该掩码返回到mask所指向的结构中 
*/

例子1:pthread线程内部绑核

#include
#include
#include
#include
#include

#define _GNU_SOURCE
#include
#include
#include
#include
#define THREAD_MAX_NUM 200  //1个CPU内的最多进程数

int num=0;  //cpu中核数
void* threadFun(void* arg)  //arg  传递线程标号(自己定义)
{
    cpu_set_t mask;  //CPU核的掩码mask
    cpu_set_t get;   //获取cpu掩码
    int *a = (int *)arg; 
    int i;

    printf("the thread is:%d\n",*a);  //显示是第几个线程
    CPU_ZERO(&mask);    //置空
    CPU_SET(*a,&mask);   //设置亲和力值,绑定cpu核到(*a)核上
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1)//设置线程CPU亲和力
    {
        printf("warning: could not set CPU affinity \n");
    }

    CPU_ZERO(&get);
    if (sched_getaffinity(0, sizeof(get), &get) == -1)//获取线程CPU亲和力
    {
         printf("warning: cound not get thread affinity, continuing...\n");
    }
    for (i = 0; i < num; i++)
    {
        if (CPU_ISSET(i, &get))//判断线程与哪个CPU有亲和力
        {
          printf("this thread %d is running processor : %d\n", i,i);
        }
    }

   return NULL;
}

int main(int argc, char* argv[])
{
   int tid[THREAD_MAX_NUM];
   int i;
   pthread_t thread[THREAD_MAX_NUM];

   num = sysconf(_SC_NPROCESSORS_CONF);  //获取核数for(i=0;i 
  

 例子2:main主线程绑核

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include 
#include 
#include 
#include 
#include 
 
void* testfunc(void* t) {
  while(1);
  return NULL; 
}
 
int main()
{
  cpu_set_t mask;
  printf("pid=%d\n", getpid());
  CPU_ZERO(&mask);
  CPU_SET(0, &mask);//将cpu0绑定
  sched_setaffinity(0, sizeof(cpu_set_t), &mask) ;
  
  pthread_t tid1;//创建线程1
  if (pthread_create(&tid1, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n");
    return -1;   
  }
  pthread_join(tid1, NULL);
  return 0;
}

例子3:main主函数内部绑线程核

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include 
#include 
#include 
#include 
#include 
 
void* testfunc(void* t) {
  int i = 3;
  while(i) {
     sleep(5);
     printf("tid=%d,cpu=%d\n",pthread_self(), sched_getcpu());
     i--;
  }return NULL; 
}
 
int main()
{
  cpu_set_t mask;
  printf("pid=%d\n", getpid());
  CPU_ZERO(&mask);
  
  pthread_t tid1;
  if (pthread_create(&tid1, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n");
    return -1;   
  }
  pthread_t tid2;
  if (pthread_create(&tid2, NULL, (void *)testfunc, NULL) != 0) 
  {      
    fprintf(stderr, "thread create failed\n");
    return -1;   
  } 
  printf("tid1=%d,tid2=%d\n", tid1,tid2);
 
  CPU_SET(0, &mask);//绑定cpu0,线程绑定
  pthread_setaffinity_np(tid1, sizeof(cpu_set_t), &mask) ;
  
  //清除之前设置,重新设置绑定cpu3
  CPU_ZERO(&mask);
  CPU_SET(3, &mask);
  pthread_setaffinity_np(tid2, sizeof(cpu_set_t), &mask) ;
  
  pthread_join(tid1, NULL);
  pthread_join(tid1, NULL);
  return 0;
}

你可能感兴趣的:(linux)