进程,线程,内核设置cpu亲和性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luckywang1103/article/details/82759780

进程与cpu绑定

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

SCHED_SETAFFINITY(2)                                                                      Linux Programmer's Manual                                                                     SCHED_SETAFFINITY(2)

NAME
       sched_setaffinity, sched_getaffinity - set and get a process's CPU affinity mask

SYNOPSIS
       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <sched.h>

       int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
       /*该函数设置进程为pid的这个进程,让它运行在mask所设定的CPU上.如果pid的值为0,
        *则表示指定的是当前进程,使当前进程运行在mask所设定的那些CPU上.
        *第二个参数cpusetsize是mask所指定的数的长度.通常设定为sizeof(cpu_set_t).
        *如果当前pid所指定的进程此时没有运行在mask所指定的任意一个CPU上,
        *则该指定的进程会从其它CPU上迁移到mask的指定的一个CPU上运行.*/

       int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
       /*该函数获得pid所指示的进程的CPU位掩码,并将该掩码返回到mask所指向的结构中.
        *即获得指定pid当前可以运行在哪些CPU上.
        *同样,如果pid的值为0.也表示的是当前进程*/

RETURN VALUE
       On success, sched_setaffinity() and sched_getaffinity() return 0.  On error, -1 is returned, and errno is set appropriately.

设置cpu affinity还需要用到一下宏函数

void CPU_ZERO (cpu_set_t *set)
/*这个宏对 CPU 集 set 进行初始化,将其设置为空集。*/
void CPU_SET (int cpu, cpu_set_t *set)
/*这个宏将 指定的 cpu 加入 CPU 集 set 中*/
void CPU_CLR (int cpu, cpu_set_t *set)
/*这个宏将 指定的 cpu 从 CPU 集 set 中删除。*/
int CPU_ISSET (int cpu, const cpu_set_t *set)
/*如果 cpu 是 CPU 集 set 的一员,这个宏就返回一个非零值(true),否则就返回零(false)。*/

下面下一个具体的例子:将当前进程绑定到0、1、2、3号cpu上

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/* sysconf( _SC_NPROCESSORS_CONF ) 查看cpu的个数;打印用%ld长整。
 * sysconf( _SC_NPROCESSORS_ONLN ) 查看在使用的cpu个数;打印用%ld长整 */
int main(int argc, char **argv)
{
    int cpus = 0;
    int  i = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_CONF);
    printf("cpus: %d\n", cpus);

    CPU_ZERO(&mask);    /* 初始化set集,将set置为空*/
    CPU_SET(0, &mask);  /* 依次将0、1、2、3号cpu加入到集合,前提是你的机器是多核处理器*/
    CPU_SET(1, &mask);
    CPU_SET(2, &mask);
    CPU_SET(3, &mask);
    
    /*设置cpu 亲和性(affinity)*/
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
        printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    }   
    usleep(1000); /* 让当前的设置有足够时间生效*/

    /*查看当前进程的cpu 亲和性*/
    CPU_ZERO(&get);
    if (sched_getaffinity(0, sizeof(get), &get) == -1) {
        printf("get CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    }   
    
    /*查看运行在当前进程的cpu*/
    for(i = 0; i < cpus; i++) {

        if (CPU_ISSET(i, &get)) { /*查看cpu i 是否在get 集合当中*/
            printf("this process %d of running processor: %d\n", getpid(), i); 
        }    
    }
    sleep(3); //让程序停在这儿,方便top命令查看
       
    return 0;
}

运行结果如下:

[root@localhost test]# ./test    
cpus: 24
this process 2848 of running processor: 0
this process 2848 of running processor: 1
this process 2848 of running processor: 2
this process 2848 of running processor: 3

另外一份我自己写的参考代码位置:绑定进程到指定cpu


线程与cpu绑定

线程绑定于进程的区别是所用函数不一样,线程绑定用到下面两个函数

NAME
       pthread_setaffinity_np, pthread_getaffinity_np - set/get CPU affinity of a thread

SYNOPSIS
       #define _GNU_SOURCE             /* See feature_test_macros(7) */
       #include <pthread.h>

       int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
                                  const cpu_set_t *cpuset);
       int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,
                                  cpu_set_t *cpuset);

       Compile and link with -pthread.

DESCRIPTION
       The  pthread_setaffinity_np()  function  sets the CPU affinity mask of the thread thread to the CPU set pointed to by cpuset.  If the call is successful, and the thread is not
       currently running on one of the CPUs in cpuset, then it is migrated to one of those CPUs.

       The pthread_getaffinity_np() function returns the CPU affinity mask of the thread thread in the buffer pointed to by cpuset.

       For more details on CPU affinity masks, see sched_setaffinity(2).  For a description of a set of macros that can be used to manipulate and inspect CPU sets, see CPU_SET(3).

       The argument cpusetsize is the length (in bytes) of the buffer pointed to by cpuset.  Typically, this argument would be specified as sizeof(cpu_set_t).  (It may be some  other
       value, if using the macros described in CPU_SET(3) for dynamically allocating a CPU set.)

RETURN VALUE
       On success, these functions return 0; on error, they return a nonzero error number

下面同样是个具体的例子:将当前线程绑定到0、1、2、3号cpu上

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>

void *testfunc(void *arg)
{
    int i, cpus = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_CONF);
    printf("this system has %d processor(s)\n", cpus);
    
    CPU_ZERO(&mask);
    for (i = 0; i < 4; i++) { /*将0、1、2、3添加到集合中*/
        CPU_SET(i, &mask);
    }   

    /* 设置cpu 亲和性(affinity)*/
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
        fprintf(stderr, "set thread affinity failed\n");
    }   
    
    /* 查看cpu 亲和性(affinity)*/
    CPU_ZERO(&get);
    if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
        fprintf(stderr, "get thread affinity failed\n");
    }   

    /* 查看当前线程所运行的所有cpu*/
    for (i = 0; i < cpus; i++) {
        if (CPU_ISSET(i, &get)) {
            printf("this thread %d is running in processor %d\n", (int)pthread_self(), i); 
        }   
    }   
    sleep(3); //查看
    
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[])
{
    pthread_t tid;
    if (pthread_create(&tid, NULL, (void *)testfunc, NULL) != 0) {
        fprintf(stderr, "thread create failed\n");
        return -1; 
    }   

    pthread_join(tid, NULL);
    return 0;
}

运行结果如下:

[root@localhost thread]# ./test                      
this system has 24 processor(s)
this thread 2812323584 is running in processor 0
this thread 2812323584 is running in processor 1
this thread 2812323584 is running in processor 2
this thread 2812323584 is running in processor 3

内核中绑定cpu

在内核里如果要指定cpu, smp_call_function_single(),定义在kernel/smp.c


参考文章

  1. linux进程、线程与cpu的亲和性(affinity)

猜你喜欢

转载自blog.csdn.net/luckywang1103/article/details/82759780