最可靠的方法是直接读取 /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq,该路径下每个文件对应一个逻辑核心,内容为实时真实频率(khz),不经过内核缓存,只要 cpufreq 驱动加载即准确。

直接读 /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 是最可靠的方法
这个路径下每个 cpu0、cpu1 … 对应一个逻辑核心,scaling_cur_freq 文件内容就是该核当前真实运行频率(单位:kHz)。它不经过内核缓存,也不依赖用户态工具,只要 cpufreq 驱动已加载,就准。
实操建议:
- 先确认路径存在:
ls /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq;若报错“No such file”,说明驱动没加载(查dmesg | grep -i "cpu.*freq") - 一次性看全部核心:
cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 2>/dev/null - 带核编号格式化输出:
for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq; do echo "$(basename $(dirname $i)): $(cat $i 2>/dev/null) kHz"; done - 注意:值为 0 表示该核 offline 或被 isolcpus 隔离;空输出通常意味着该核未启用 cpufreq(如某些 ARM 或嵌入式平台)
cpupower monitor 能持续采样但只适用于调试场景
它每秒输出一行,明确列出每个 cpuX 的当前频率(kHz),还附带 C-state 和负载信息,适合抓取频率波动、验证降频是否触发。
容易踩的坑:
- 必须 root 权限,且内核需启用
CONFIG_X86_ACPI_CPUFREQ(Intel/AMD x86)或对应驱动 - 虚拟机中基本不可用——KVM/Xen 会屏蔽底层寄存器,
cpupower monitor直接退出或报错 - 默认无时间戳,要对齐其他日志得自己加
date前缀,例如:while true; do echo "$(date '+%s.%N'): $(cpupower monitor -m 1 2>/dev/null | tail -n 1)"; sleep 1; done
别信 /proc/cpuinfo 的 cpu MHz 字段当实时依据
它确实显示每个核心的“当前”频率,但值来自内核软缓存,更新有延迟。高负载下刚升频,cpu MHz 可能还卡在旧值;空闲时降频后也可能滞后几百毫秒才刷新。
常见误用:
-
grep "cpu MHz" /proc/cpuinfo | head -n 1—— 只取第一个核心,完全忽略多核异步变化 - 把输出当绝对真实值——比如看到
cpu MHz : 4300.000就断定睿频满血,其实可能只是瞬时峰值,scaling_cur_freq才反映稳定运行值 - 在超线程开启的机器上,
cpu MHz对超线程逻辑核也单独输出,但它们共享物理核心频率,不能等同于独立升频能力
cpupower frequency-info --freq 返回单值,不是每核频率
它读的是硬件寄存器,比 /proc/cpuinfo 更准,但只返回一个数值,代表“当前采样核”或“主核”的频率。它不告诉你其他核是不是在跑 800MHz,也不反映负载不均导致的频率分化。
适用场景有限:
- 快速确认系统有没有升频能力(比如 BIOS 关了 Turbo,这里永远卡在 base frequency)
- 配合
cpupower frequency-set做策略验证时作参考 - 但绝不能替代
scaling_cur_freq或cpupower monitor来诊断某核卡频、调度异常等问题
真正复杂的地方在于:多插槽服务器上,不同 CPU socket 的频率可能由各自电源管理域控制,scaling_cur_freq 是唯一能横向比对全部逻辑核的路径;而任何命令行工具只要没显式遍历 cpu*,本质上都只给你一个盲点视角。











