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 <sched.h>
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<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/sysinfo.h>
#include<unistd.h>
#define _GNU_SOURCE
#include<sched.h>
#include<ctype.h>
#include<string.h>
#include<pthread.h>
#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<num;i++)
{
tid[i] = i; //每个线程必须有个tid[i]
pthread_create(&thread[i],NULL,threadFun,(void*)&tid[i]);
}
for(i=0; i< num; i++)
{
pthread_join(thread[i],NULL);//等待所有的线程结束,线程为死循环所以CTRL+C结束
}
return 0;
}
例子2:main主线程绑核
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
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 <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <pthread.h>
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;
}