執行緒繫結cpu核心的程式碼研究

chromeplugin發表於2024-10-31

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;
}

相關文章