linux需用pthread_getaffinity_np获取线程亲和性,须正确初始化cpu_set_t并检查返回值;windows应使用getthreadgroupaffinity而非getprocessaffinitymask;跨平台时禁用sizeof(cpu_set_t),改用cpu_alloc系列函数动态分配内存。

Linux下用pthread_getaffinity_np读取线程亲和性掩码
Linux没有标准POSIX接口获取线程亲和性,必须用GNU扩展的pthread_getaffinity_np。它把当前线程的CPU掩码写入你提供的cpu_set_t缓冲区,但容易因缓冲区大小不对而静默失败。
-
cpu_set_t不是固定大小类型,实际大小依赖系统CPU数量,必须用CPU_ZERO(&set)初始化,再传给pthread_getaffinity_np - 调用后要检查返回值:
int ret = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &set),非0表示失败(比如ret == EINVAL说明sizeof(cpu_set_t)不够大) - 若系统CPU数超过1024,
cpu_set_t可能不足以容纳全部位,此时应改用syscall(SYS_gettid)配合/proc/[tid]/status里的Cpus_allowed_list字段
Windows下用GetThreadGroupAffinity替代GetProcessAffinityMask
Windows里GetProcessAffinityMask返回的是进程默认亲和性,不是当前线程的实际掩码。真正有效的是GetThreadGroupAffinity,它支持多组CPU(NUMA节点),且返回GROUP_AFFINITY结构体。
-
GROUP_AFFINITY中Mask字段是KAFFINITY类型(64位整数),对应当前组内CPU位图;Group字段标识NUMA组号 - 必须先调用
GetActiveProcessorCount或遍历GetActiveProcessorGroupCount确认组数,单组场景下Group通常为0 - 如果程序未显式设置过线程亲和性,
Mask值可能等于进程亲和性掩码,也可能被系统调度器动态调整——GetThreadGroupAffinity返回的是内核当前记录的值,不是“理想值”
跨平台封装时别硬编码cpu_set_t尺寸
很多跨平台代码直接写sizeof(cpu_set_t),但在glibc 2.35+中,cpu_set_t内部结构已改为动态大小,旧代码会截断高位CPU位。正确做法是用CPU_ALLOC系列函数。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 优先用
cpu_set_t *set = CPU_ALLOC(num_cpus)分配内存,再用CPU_ALLOC_SIZE(num_cpus)获取真实所需字节数 - 调用
pthread_getaffinity_np(tid, cpusetsize, set)时,第二个参数必须是CPU_ALLOC_SIZE返回值,不能是sizeof(cpu_set_t) - 最后必须
CPU_FREE(set)释放,否则内存泄漏——这点常被忽略,尤其在频繁查询亲和性的服务进程中
注意线程创建后亲和性可能被继承或重置
子线程默认继承父线程亲和性掩码,但某些场景下会被覆盖:比如用std::thread构造时未指定策略,或线程池复用线程对象后未显式重置。
- Linux下
clone()系统调用默认继承,但若父线程之前调用过sched_setaffinity(0, ...),子线程也会继承该掩码 - Windows下新线程默认使用进程亲和性,除非显式调用
SetThreadGroupAffinity - 调试时发现掩码“变回默认值”,大概率是其他模块调用了
pthread_setaffinity_np或SetThreadGroupAffinity覆盖了原有设置,建议在关键路径前后都做一次读取验证
亲和性掩码本身不保证实时绑定,它只是调度器的参考约束;即使读到非零掩码,线程仍可能被迁移到掩码外CPU上——特别是当目标CPU忙、发生中断或内核触发负载均衡时。真正需要强绑定的场景,得配合sched_setaffinity或SetThreadGroupAffinity主动设置,并留意权限问题(Linux需CAP_SYS_NICE)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










