Windows下用GetLogicalProcessorInformation获取映射需两次调用:首次传nullptr获取缓冲区大小,二次分配内存后遍历RelationProcessorCore条目,解析ULONG_PTR类型的ProcessorMask位图以确定各物理核心对应的逻辑处理器;Linux则通过遍历/sys/devices/system/cpu/cpu*/topology/thread_siblings_list等文件构建映射。

Windows 下用 GetLogicalProcessorInformation 获取核心/逻辑处理器映射
Windows 提供了最直接的 API:通过 GetLogicalProcessorInformation 一次性拿到所有逻辑处理器与物理核心、NUMA 节点、缓存层级的隶属关系。它返回的是 SYSTEM_LOGICAL_PROCESSOR_INFORMATION 数组,每个元素带 Relationship 字段标明类型(如 RelationProcessorCore、RelationNumaNode),关键在于解析 ProcessorMask —— 这是一个位掩码,每一位对应一个逻辑处理器编号(0 ~ N-1),置 1 表示该逻辑处理器属于当前描述的物理核心。
实操要点:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 必须循环调用两次:第一次传
nullptr获取所需缓冲区大小,第二次分配足够内存再调用 -
ProcessorMask是ULONG_PTR类型,注意在 32/64 位进程下宽度不同;跨平台代码建议用std::bitset或手动按字节拆解 - 一个
RelationProcessorCore条目可能包含多个逻辑处理器(超线程),其ProcessorMask的 bit count 就是该核心的逻辑线程数(通常是 1 或 2) - 别混淆
GetSystemInfo返回的dWNumberOfProcessors—— 那只是总逻辑处理器数,不带拓扑信息
Linux 下读取 /sys/devices/system/cpu 文件系统
Linux 没有统一 syscall,但 /sys 提供了稳定、人可读的拓扑接口。每个逻辑 CPU(如 cpu0)目录下有 topology/core_id、topology/physical_package_id、topology/thread_siblings_list 等文件,能还原出完整映射。
实操要点:
立即学习“C++免费学习笔记(深入)”;
- 遍历
/sys/devices/system/cpu/cpu[0-9]*目录,跳过软链接(如cpu0可能是online的符号链接) -
topology/thread_siblings_list是逗号分隔的逻辑 CPU 列表(如"0,4"),表示这些逻辑 CPU 共享同一个物理核心;而topology/core_id是该核心在封装内的局部 ID,需结合physical_package_id才能全局唯一标识物理核心 - 不要依赖
/proc/cpuinfo的core id和cpu cores字段——它们格式松散、字段缺失常见,且不保证顺序或完整性 - 注意权限:某些嵌入式或容器环境可能挂载时未暴露
/sys/devices/system/cpu的全部内容
C++ 跨平台封装时最易踩的坑:位掩码解析与 NUMA 干扰
即使你分别实现了 Windows/Linux 版本,合并成统一接口时,最容易出错的是把“逻辑 CPU 编号”和“OS 报告的索引”混为一谈。例如:Linux 的 cpu0 对应逻辑编号 0,但 Windows 的 ProcessorMask 中 bit 0 也代表逻辑 CPU 0 —— 表面一致,实际在 NUMA 多插槽机器上,两个 OS 对“编号连续性”的假设可能不同(尤其热插拔后)。
关键细节:
- 永远以逻辑 CPU 编号(0-based 整数)为唯一键,而不是目录名或数组下标
- Windows 下一个物理核心的
ProcessorMask可能横跨多个ULONG_PTR(当逻辑 CPU 总数 > 64),此时必须检查GetLogicalProcessorInformationEx+RelationGroup(推荐用于 >64 核场景) - Linux 下
thread_siblings_list可能含范围(如"0-3"),需正确解析,不能简单按逗号切分 - 不要假定超线程总是成对出现:某些服务器 BIOS 可单独关闭部分 SMT 线程,导致同一核心下只有 1 个逻辑 CPU 在线
验证映射是否正确的最小检查项
拿到映射表后,光看数据结构不等于正确。真正可靠的验证方式是交叉比对三个约束:
- 所有逻辑 CPU 编号(0 ~ N-1)必须恰好出现在且仅出现在一个物理核心条目中(即所有
ProcessorMask或thread_siblings_list的并集 = 全集,交集为空) - 每个物理核心条目内逻辑 CPU 数量 ≤ 当前系统的最大超线程数(可通过
__cpuid查EDX[28]或/proc/cpuinfo的bugs字段间接判断) - 同一物理封装(package)下的所有核心,其
core_id或core_num必须互异;重复意味着解析错误或硬件异常
复杂点不在获取,而在确认你拿到的“映射”确实是 OS 当前真实调度视图 —— 尤其在容器、WSL、虚拟化环境中,/sys 或 API 返回的可能是虚拟拓扑,而非宿主机物理布局。

















