sched_setaffinity – 将线程&进程运行在期望的CPU核心上
CPU亲和性
是指进程或线程在运行时倾向于在某个或某些CPU核心上执行,而不是随机或频繁地在不同的核心之间切换。
CPU亲和性利用CPU缓存的局部性,减少缓存失效和进程或线程迁移的开销,避免频繁地在不同的核心之间切换,提高性能
CPU亲和性分为软亲和性
和硬亲和性
:
软亲和性
是Linux内核进程调度器的默认特性,它会尽量让进程在上次运行的CPU核心上继续运行,但不保证一定如此,因为还要考虑各个核心的负载均衡。
硬亲和性
是Linux内核提供给用户的API,它可以让用户显式地指定进程或线程可以运行在哪些CPU核心上,或者绑定到某个特定的核心上。
使用方式
man sched_setaffinity
#查找man手册
/*sched_setaffinity():设置进程或线程的CPU亲和性掩码,表示它可以运行在哪些核心上。sched_getaffinity():获取进程或线程的CPU亲和性掩码,表示它当前可以运行在哪些核心上。CPU_ZERO():操作CPU亲和性掩码的宏,用于清空某个核心是否在掩码中。CPU_SET():操作CPU亲和性掩码的宏,用于设置某个核心是否在掩码中。CPU_CLR():操作CPU亲和性掩码的宏,用于清除某个核心是否在掩码中。CPU_ISSET():操作CPU亲和性掩码的宏,用于检查某个核心是否在掩码中。
*/
#include <sched.h>
//sysconf()查询系统限制和配置信息
int num = sysconf(_SC_NPROCESSORS_CONF); //_SC_NPROCESSORS_CONF:可以同时运行的CPU数量
self_id = syscall(__NR_gettid);//获取进程号和线程号
cpu_set_t mask; // 1.创建一 cpu 亲和性掩码
CPU_ZERO(&mask); // 2.清空
CPU_SET(self_id % num, &mask); // 3.设置 亲和性掩码
if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { // 4.设置当前线程的cpu亲和性return -1;
}
/*
pid:表示要设置的进程或线程的ID,如果为0,则表示当前进程或线程;
cpusetsize:表示mask指针指向的数据的长度,通常为sizeof(cpu_set_t);
mask:是一个指向cpu_set_t类型的指针,cpu_set_t是一个不透明的结构体,用于表示CPU亲和性掩码,需要使用一些宏来操作它,如CPU_ZERO, CPU_SET, CPU_CLR等。
成功时返回0,失败时返回-1,并设置errno为相应的错误码。可能的错误码有:EFAULT: mask指针无效EINVAL: mask中没有有效的CPU核心EPERM: 调用者没有足够的权限
int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
*/
原理
是通过设置进程或线程的CPU亲和性掩码,来指定它可以运行在哪些CPU核心上。CPU亲和性掩码是一个位图,每一位对应一个CPU核心,如果某一位为1,表示该进程或线程可以运行在该核心上,否则不能。