Linux内核:进程管理——CPU亲和力设置

1. 获取CPU核数

int CPU_NUM = sysconf(_SC_NPROCESSORS_CONF);

2. 线程绑定CPU核心

① 概念

CPU绑定 指的是在多 CPU 的系统中将进程或线程绑定到指定的 CPU 核上去执行。在 Linux 中,我们可以利用 CPU affinity(亲和性) 属性把进程绑定到一个或多个 CPU 核上。

CPU Affinity 是进程的一个属性,这个属性指明了进程调度器能够把这个进程调度到哪些CPU上。
该属性要求进程在某个指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器。

CPU Affinity分为2种:

  • soft affinity
  • hard affinity

soft affinity 只是一个建议,如果不可避免,调度器还是会把进程调度到其它的CPU上去执行;

hard affinity 则是调度器必须遵守的规则, 2.6 以上版本的 Linux 内核可以让开发人员可以编程实现 hard affinity 。

② 函数

进程与CPU的绑定 在Linux中,用结构体cpu_set_t来表示 CPU Affinity 掩码,同时定义了一系列的宏来用于操作进程的可调度CPU集合:

#define _GNU_SOURCE

#include <sched.h>

void CPU_ZERO(cpu_set_t *set); // 清除集合的内容,让其不包含任何 CPU。
void CPU_SET(int cpu, cpu_set_t *set); // 添加 CPU 到集合中
void CPU_CLR(int cpu, cpu_set_t *set); // 从集合中移除 CPU
int CPU_ISSET(int cpu, cpu_set_t *set); // 测试 CPU 是否在集合中
int CPU_COUNT(cpu_set_t *set); // 返回集合中包含的 CPU 数量

在Linux中,可以使用以下两个函数 设置和获取进程的 CPU Affinity 属性:

#define _GNU_SOURCE

#include <sched.h>

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

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

/**
 * 线程与 CPU 的绑定
*/
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);

另外可以通过下面的函数获知当前进程运行在哪个 CPU 上:

int sched_getcpu(void);

如果调用成功,该函数返回一个非负的 CPU 编号值。

③ 例子

以下函数根据不同进程调用时输入的不同数值,将不同进程绑定到不同的核,从而将 CPU 的多核心利用起来

void func(int i) {
    cpu_set_t mask;
    CPU_ZERO(&mask);
    int cpu_num = sysconf(_SC_NPROCESSORS_CONF);
    if (cpu_num == 0) {
    	cpu_num = 1;
    }
    CPU_SET((i % cpu_num), &mask);
    sched_setaffinity(0, sizeof(cpu_set_t), &mask);
}

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

原文作者:精通Linux内核

原文地址:Linux内核:进程管理——CPU亲和力设置 - 知乎(版权归原文作者所有,侵权留言联系删除)

猜你喜欢

转载自blog.csdn.net/m0_74282605/article/details/130117424