Linux下应调用sched_getaffinity(0, sizeof(cpuset), &cpuset)获取当前线程亲和性掩码,须先CPU_ZERO清空位图,再用CPU_ISSET遍历sysconf(_SC_NPROCESSORS_ONLN)获知的逻辑CPU数打印允许的核心编号。

Linux下用sched_getaffinity获取CPU亲和性掩码
在Linux上,C++程序要读取当前进程的CPU亲和性,必须调用sched_getaffinity。它不返回布尔值或整数,而是把掩码写入你提供的cpu_set_t缓冲区,所以第一步是分配足够大的缓冲区。
常见错误是直接传栈上未初始化的cpu_set_t——它大小依赖系统CPU数量,不能靠sizeof(cpu_set_t)硬编码;更安全的做法是用CPU_ZERO清零后配合CPU_SET逐位检查,或直接用CPU_COUNT统计已设置的CPU数。
-
cpu_set_t必须用CPU_ZERO(&set)初始化,否则可能含随机位 - 调用前检查返回值:失败时
errno可能是EINVAL(缓冲区太小)或EPERM(权限不足) - 掩码中第n位为1表示进程可运行在逻辑CPU
n上(从0开始编号)
Windows下用GetProcessAffinityMask替代
Windows没有POSIX亲和性掩码概念,对应的是进程亲和性掩码(DWORD_PTR类型),用GetProcessAffinityMask获取。注意它返回两个掩码:dwProcessAffinityMask是进程允许运行的CPU集合,dwSystemAffinityMask是系统当前可用的CPU集合。
容易忽略的是:该函数不修改进程当前调度策略,只读取已有设置;若进程从未显式设置过亲和性,返回的掩码通常是全1(即所有可用逻辑处理器)。
- 必须传入非空指针,任一参数为
nullptr会导致调用失败 - 返回值为
BOOL,需用GetLastError()进一步判断错误类型(如ERROR_ACCESS_DENIED) - 掩码位宽取决于系统架构:x64下
DWORD_PTR是64位,但实际有效位数由dwSystemAffinityMask决定
跨平台封装要注意位宽与CPU编号差异
Linux的cpu_set_t是位数组,最大支持CPU数由CPU_SETSIZE定义(通常1024);Windows掩码是纯整数,最多支持64个逻辑处理器(除非用GetProcessGroupAffinity处理NUMA节点)。两者无法直接互转。
若你写跨平台代码,别试图统一成一个整数掩码——Linux可能有上百CPU核心,而Windows原生掩码只覆盖低64位。更稳妥的方式是抽象为std::vector<bool></bool>或std::bitset(预估最大CPU数),再按平台分别填充。
- 不要用
unsigned long接收Linux掩码——它不是单个整数,而是结构体 - Windows下若需支持超过64核,必须调用
GetProcessGroupAffinity并遍历每个组 - 获取到掩码后,建议立刻用
sysconf(_SC_NPROCESSORS_ONLN)(Linux)或GetActiveProcessorCount(ALL_PROCESSOR_GROUPS)(Windows)验证CPU总数是否匹配
为什么taskset -p $PID显示结果和程序读出来不一致?
这是最常被问到的问题:taskset输出的十六进制掩码和你的sched_getaffinity结果对不上,通常是因为taskset默认以“最低有效位对应CPU 0”方式打印,而你用CPU_ISSET(n, &set)检查时顺序一致,但若手动解析cpu_set_t内存布局(比如强转成unsigned long*),就可能因字节序或位域排列出错。
根本原因在于cpu_set_t是不透明类型,其内部布局未标准化。唯一可靠方式是用CPU_*宏操作,而不是按字节/字解析原始内存。
- 绝对不要用
memcpy或reinterpret_cast把cpu_set_t当整数数组处理 -
taskset的输出格式受LIBC版本影响,glibc 2.35+ 改为按CPU索引升序打印,旧版可能反序 - 验证一致性最简单的方法:用
CPU_COUNT(&set)得到启用CPU数,再用taskset -cp $PID看列出的CPU编号个数是否相同
实际调试时,最麻烦的不是读取,而是确认你拿到的是“进程当前生效”的掩码——它可能被cgroups、容器运行时或父进程继承覆盖,尤其在Docker/Kubernetes环境中,sched_getaffinity返回的往往是cgroup cpuset限制后的子集,而非原始设置。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











