/proc/cpuinfo

本文详细解释了CPU中的物理核心与逻辑核心的区别,介绍了如何通过/proc/cpuinfo文件来查看物理CPU个数、逻辑CPU个数、CPU核心数及主频等信息,并提供了具体的命令示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在看affinity时发现,有cpu的物理核心和逻辑核心的概念,两个有什么区别呢?

 

物理核心数,是cpu中真实的核心数。每个核心有独立缓存。

逻辑核心数,是通过超线程技术得到的核心数,逻辑核心共享缓存。

 

如:单核处理器开启超线程,逻辑核心是2,物理核心是1。

 

如果在/proc/cpuinfo中看物理核心和逻辑核心呢?

1.具有相同core id的cpu是同一个core的超线程。
2.具有相同physical id的cpu是同一颗cpu封装的线程或者cores。

 

具体如下:

 

1. 查看物理CPU的个数(physical CPU number)
#cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
 
2. 查看逻辑CPU的个数(
logical CPU number)

#cat /proc/cpuinfo | grep "processor" | wc -l
 
3. 查看CPU是几核(core number in a physical CPU)
#cat /proc/cpuinfo |grep "cores" | uniq
 
4. 查看CPU的主频
#cat /proc/cpuinfo | grep MHz | uniq

 

5. 查看每个physical cpu上core id的数量,即为每个物理CPU上的core的个数
#cat /proc/cpuinfo | grep "core id"

 

6. 是否为超线程?

如果有两个逻辑CPU具有相同的”core id”,那么超线程是打开的。
每个物理CPU中逻辑CPU(可能是core, threads或both)的个数:
#cat /proc/cpuinfo | grep "siblings"

 

/proc/cpuinfo 文件包含系统上每个处理器的数据段落。/proc/cpuinfo 描述中有 6 个条目适用于多内核和超线程(HT)技术检查:processor, vendor id, physical id, siblings, core id 和 cpu cores。
processor 条目包括这一逻辑处理器的唯一标识符。
physical id 条目包括每个物理封装的唯一标识符。
core id 条目保存每个内核的唯一标识符。
siblings 条目列出了位于相同物理封装中的逻辑处理器的数量。
cpu cores 条目包含位于相同物理封装中的内核数量。
如果处理器为英特尔处理器,则 vendor id 条目中的字符串是 GenuineIntel。

1.拥有相同 physical id 的所有逻辑处理器共享同一个物理插座。每个 physical id 代表一个唯一的物理封装。
2.Siblings 表示位于这一物理封装上的逻辑处理器的数量。它们可能支持也可能不支持超线程(HT)技术。
3.每个 core id 均代表一个唯一的处理器内核。所有带有相同 core id 的逻辑处理器均位于同一个处理器内核上。
4.如果有一个以上逻辑处理器拥有相同的 core id 和 physical id,则说明系统支持超线程(HT)技术。
5.如果有两个或两个以上的逻辑处理器拥有相同的 physical id,但是 core id 不同,则说明这是一个多内核处理器。cpu cores 条目也可以表示是否支持多内核。

判断CPU是否64位,检查cpuinfo中的flags区段,看是否有lm标识。
Are the processors 64-bit?   
A 64-bit processor will have lm ("long mode") in the flags section of cpuinfo. A 32-bit processor will not.

 

 

 

 

参考文献:

1. http://www.51testing.com/html/38/225738-236367.html

2. http://www.searchtb.com/2012/12/玩转cpu-topology.html

<think>我们正在讨论的是`cat /proc/cpuinfo`的实现原理和源代码。在Linux中,`/proc`是一个虚拟文件系统,它不占用磁盘空间,而是由内核动态生成。当用户读取`/proc/cpuinfo`时,内核会实时收集CPU信息并格式化输出。 ### 1. **proc文件系统注册** 在Linux内核中,`/proc/cpuinfo`的注册通常在`arch`目录下的特定架构文件中。例如,对于x86架构,可以在`arch/x86/kernel/cpu/proc.c`中找到注册代码。以下是关键代码片段: ```c static int __init proc_cpuinfo_init(void) { proc_create_single("cpuinfo", 0, NULL, show_cpuinfo); return 0; } fs_initcall(proc_cpuinfo_init); ``` 这里,`proc_create_single`函数注册了`/proc/cpuinfo`文件,并指定了当文件被读取时调用的函数`show_cpuinfo`[^1]。 ### 2. **核心函数`show_cpuinfo()`** `show_cpuinfo`函数负责生成`/proc/cpuinfo`的内容。该函数会遍历系统中的每个CPU(逻辑核),并输出每个CPU的信息。以下是x86架构的简化实现(Linux 5.15内核): ```c static int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_x86 *c = v; unsigned int cpu; int i; cpu = c->cpu_index; seq_printf(m, "processor\t: %u\n", cpu); // 逻辑处理器编号 // 输出厂商信息 if (c->x86_vendor_id[0]) seq_printf(m, "vendor_id\t: %s\n", c->x86_vendor_id); else seq_printf(m, "vendor_id\t: unknown\n"); // 输出CPU家族、型号等信息 seq_printf(m, "cpu family\t: %d\n", c->x86); seq_printf(m, "model\t\t: %d\n", c->x86_model); seq_printf(m, "model name\t: %s\n", c->x86_model_id); // 输出主频信息 seq_printf(m, "stepping\t: %d\n", c->x86_stepping); seq_printf(m, "microcode\t: 0x%x\n", c->microcode); seq_printf(m, "cpu MHz\t\t: %.3f\n", c->cpufreq_mhz); // 输出缓存信息 seq_printf(m, "cache size\t: %u KB\n", c->x86_cache_size); // 输出物理核和逻辑核信息 seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", c->booted_cores); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); // 输出标志(features) seq_puts(m, "flags\t\t:"); for (i = 0; i < 32*NCAPINTS; i++) if (cpu_has(c, i) && x86_cap_flags[i] != NULL) seq_printf(m, " %s", x86_cap_flags[i]); seq_putc(m, '\n'); // ... 其他信息(如bogomips、clflush等) seq_printf(m, "bogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); return 0; } ``` ### 3. **关键数据结构** - **`struct cpuinfo_x86`**(`arch/x86/include/asm/processor.h`): 该结构体存储了CPU的详细信息,包括厂商、型号、缓存大小、主频等[^3]。 ```c struct cpuinfo_x86 { __u8 x86_vendor; /* CPU vendor */ char x86_vendor_id[16]; /* Vendor ID, e.g. "GenuineIntel" */ __u8 x86_model; __u8 x86_stepping; char x86_model_id[64]; /* Model name, e.g. "Intel(R) Core(TM) i7-10700K" */ __u16 x86_cache_size; /* Cache size in KB */ __u8 phys_proc_id; /* Physical processor ID (for multi-socket systems) */ __u8 cpu_core_id; /* Core ID within the physical package */ unsigned int booted_cores; /* Number of cores in the physical package */ unsigned int cpu_index; /* Logical CPU index (0-based) */ unsigned int loops_per_jiffy; /* Used to calculate bogomips */ // ... 其他字段 }; ``` ### 4. **CPU标志(flags)生成机制** `flags`字段通过`cpu_has()`宏检查每个CPU特性是否支持,然后从`x86_cap_flags`数组中获取对应的字符串: ```c // arch/x86/kernel/cpu/capflags.c const char * const x86_cap_flags[NCAPINTS*32] = { [X86_FEATURE_FPU] = "fpu", [X86_FEATURE_VME] = "vme", [X86_FEATURE_DE] = "de", [X86_FEATURE_PSE] = "pse", // ... 其他特性 }; ``` 在`show_cpuinfo`中,遍历所有特性位,如果设置则输出对应的字符串[^4]。 ### 5. **多核处理** 对于多核系统,`show_cpuinfo`会被每个逻辑核调用一次。这是通过`seq_file`迭代器实现的: ```c static void *c_start(struct seq_file *m, loff_t *pos) { return *pos < nr_cpu_ids ? &cpu_data(*pos) : NULL; } static void *c_next(struct seq_file *m, void *v, loff_t *pos) { (*pos)++; return c_start(m, pos); } static const struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, .show = show_cpuinfo, }; ``` `seq_file`机制会依次为每个CPU调用`show_cpuinfo`,从而输出所有逻辑核的信息。 ### 6. **proc文件系统特性** - **动态生成**:每次读取时实时收集CPU信息 - **零拷贝输出**:通过`seq_file`接口直接写入用户缓冲区 - **架构相关**:不同CPU架构(如ARM、x86)有不同的实现 ### 总结流程图 ```mermaid graph TD A[cat /proc/cpuinfo] --> B[VFS层调用procfs] B --> C[调用seq_file迭代器] C --> D[遍历每个逻辑核] D --> E[调用show_cpuinfo] E --> F1[获取cpuinfo_x86结构] E --> F2[输出基础信息] E --> F3[遍历特性标志] F1 --> G[输出processor/vendor_id等] F2 --> G[输出model/cache等] F3 --> G[输出flags列表] G --> H[返回用户空间] ``` ### 相关问题 1. 为什么`/proc/cpuinfo`中每个逻辑核的信息是重复的?[^3] 2. 如何通过内核模块修改`/proc/cpuinfo`的输出内容? 3. `cpu MHz`字段的值是如何计算的?为什么有时会变化? 4. ARM架构和x86架构的`/proc/cpuinfo`实现有何不同?[^2] 5. `flags`字段中的`ht`和`lm`分别代表什么含义?[^4] [^1]: 在Linux系统中,提供了proc文件系统显示系统的软硬件信息。如果想了解系统中CPU的提供商和相关配置信息,则可以通过`/proc/cpuinfo`文件得到。 [^2]: Linux下CPU信息查看并对`/proc/cpuinfo`进行分析。在Linux系统中,提供了proc文件系统显示系统的软硬件信息。我们来看看X86和ARM平台下CPU信息的差异。 [^3]: `processor`表示系统中逻辑处理核的编号。对于单核处理器,则可认为是其CPU编号,对于多核处理器则可以是物理核、或者使用超线程技术虚拟的逻辑核。 [^4]: `/proc/cpuinfo`里的CPU flags包含了很多用来表示CPU特征的参数,如`fpu`、`vme`等。</think>### `/proc/cpuinfo` 实现原理与内核源码分析 `/proc/cpuinfo` 是 Linux 内核通过 **proc 虚拟文件系统**动态生成的 CPU 信息接口,其核心实现涉及内核数据结构、CPU 架构相关代码和 proc 文件系统机制。以下是关键实现原理: --- ### 1. **proc 文件注册** 在 Linux 内核源码中,`/proc/cpuinfo` 的注册位于架构相关目录(如 x86 在 `arch/x86/kernel/cpu/proc.c`): ```c // arch/x86/kernel/cpu/proc.c static int __init proc_cpuinfo_init(void) { proc_create_single("cpuinfo", 0, NULL, show_cpuinfo); // 注册文件 return 0; } fs_initcall(proc_cpuinfo_init); ``` 当用户执行 `cat /proc/cpuinfo` 时,内核调用 `show_cpuinfo()` 生成内容[^1]。 --- ### 2. **核心函数 `show_cpuinfo()`** 此函数动态收集 CPU 信息并格式化输出(以 x86 架构为例): ```c static int show_cpuinfo(struct seq_file *m, void *v) { struct cpuinfo_x86 *c = &boot_cpu_data; // 获取 CPU 数据结构 int i; // 输出逻辑核编号 seq_printf(m, "processor\t: %u\n", smp_processor_id()); // 输出厂商信息 seq_printf(m, "vendor_id\t: %s\n", c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown"); // 输出 CPU 家族/型号/主频 seq_printf(m, "cpu family\t: %d\n", c->x86); seq_printf(m, "model\t\t: %d\n", c->x86_model); seq_printf(m, "model name\t: %s\n", c->x86_model_id); seq_printf(m, "stepping\t: %d\n", c->x86_stepping); seq_printf(m, "cpu MHz\t\t: %.3f\n", c->cpufreq_mhz); // 输出缓存信息 seq_printf(m, "cache size\t: %u KB\n", c->x86_cache_size); // 输出物理核与逻辑核信息 seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", c->booted_cores); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); // 输出 CPU 特性标志 (flags) seq_puts(m, "flags\t\t:"); for (i = 0; i < 32*NCAPINTS; i++) { if (cpu_has(c, i) && x86_cap_flags[i] != NULL) seq_printf(m, " %s", x86_cap_flags[i]); // 如 "sse", "avx2" } seq_putc(m, '\n'); // 输出其他信息(如 bogomips) seq_printf(m, "bogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), ...); return 0; } ``` --- ### 3. **关键数据结构** #### (1) `struct cpuinfo_x86`(定义于 `arch/x86/include/asm/processor.h`) 存储 CPU 的硬件特征信息: ```c struct cpuinfo_x86 { __u8 x86_vendor; // 厂商编号(如 Intel/AMD) char x86_vendor_id[16]; // 厂商字符串(如 "GenuineIntel") __u8 x86_model; // 型号代码 __u8 x86_stepping; // 步进版本 char x86_model_id[64]; // 完整型号名(如 "Intel(R) Core(TM) i7-10700K") __u16 x86_cache_size; // 缓存大小(KB) __u8 phys_proc_id; // 物理 CPU 编号(多插槽系统) __u8 cpu_core_id; // 物理核编号 unsigned int booted_cores; // 启用的核心数 unsigned long loops_per_jiffy; // 用于计算 bogomips // ... 其他架构相关字段 }; ``` #### (2) **CPU Flags 映射表** 特性标志(如 SSE/AVX)通过全局数组 `x86_cap_flags` 映射到字符串: ```c // arch/x86/kernel/cpu/capflags.c const char * const x86_cap_flags[NCAPINTS*32] = { [X86_FEATURE_FPU] = "fpu", [X86_FEATURE_VME] = "vme", [X86_FEATURE_AVX512] = "avx512f", // ... 共 200+ 项 }; ``` 每个标志位对应 CPUID 指令返回的功能支持状态[^4]。 --- ### 4. **多核处理机制** - **逻辑核遍历**:通过 `smp_processor_id()` 获取当前 CPU ID,由 proc 文件系统的 `seq_file` 接口自动遍历所有逻辑核。 - **数据一致性**:每个 CPU 的 `struct cpuinfo_x86` 在启动时由 `cpu_init()` 初始化,数据只读无需加锁。 --- ### 5. **proc 文件系统特性** - **动态生成**:每次读取时实时调用 `show_cpuinfo()`。 - **零拷贝优化**:通过 `seq_file` 接口直接写入用户缓冲区。 - **架构适配**:ARM/MIPS 等架构在对应目录实现自己的 `show_cpuinfo()`(如 ARM 在 `arch/arm/kernel/setup.c`)[^2]。 --- ### 6. **关键指标计算示例** 1. **`bogomips` 值** 通过启动时计算的延迟循环数得出: $$ \text{bogomips} = \frac{\text{loops\_per\_jiffy} \times \text{HZ}}{500,000} $$ 反映粗略的 CPU 速度[^3]。 2. **`cpu MHz`** 从 MSR 寄存器或 ACPI 动态获取实时频率。 --- ### 流程图解 ```mermaid graph TD A[cat /proc/cpuinfo] --> B[VFS 调用 procfs] B --> C[seq_file 迭代器] C --> D[遍历每个逻辑核] D --> E[调用 show_cpuinfo] E --> F1[读取 cpuinfo_x86 数据] E --> F2[查询 CPUID 标志] E --> F3[计算动态值 bogomips] F1 --> G[输出厂商/型号/缓存等] F2 --> G[输出 flags 列表] F3 --> G[输出 bogomips] G --> H[返回用户空间] ``` --- ### 相关问题 1. 为什么 `cpu MHz` 的值有时与硬件规格不一致? 2. ARM 架构的 `/proc/cpuinfo` 输出与 x86 有何不同?[^2] 3. `flags` 中的 `ht` 和 `lm` 分别代表什么含义?[^4] 4. 如何通过内核模块修改 `/proc/cpuinfo` 的输出? 5. `bogomips` 值能否作为 CPU 性能的准确指标?[^3] [^1]: `/proc` 是一个虚拟文件系统,在系统启动后挂载在 `/proc` 上,包含内核和系统信息。 [^2]: Linux 下 CPU 信息查看并对 `/proc/cpuinfo` 进行分析,不同架构(如 X86 和 ARM)输出有差异。 [^3]: `bogomips` 是在系统内核启动时粗略测算的 CPU 速度(Million Instructions Per Second)。 [^4]: `/proc/cpuinfo` 里的 CPU flags 包含表示 CPU 特性的参数,如 `fpu`、`sse`、`avx` 等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值