直接读/sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq最可靠,它是唯一能同时获取各逻辑核实时频率的原生方法,单位khz,无缓存、无延迟;需先确认cpufreq驱动已加载,且核心处于online状态。

直接读 /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 最可靠
这是唯一能同时看到每个逻辑核心当前频率的原生方法,单位是 kHz,比如 2400000 就是 2.4 GHz。它不依赖用户态工具,也不走内核缓存,路径真实、响应及时。
实操建议:
- 先确认 cpufreq 接口可用:
ls /sys/devices/system/cpu/cpu0/cpufreq/,若报错或目录为空,说明驱动没加载(如intel_cpufreq或acpi-cpufreq),查dmesg | grep -i "cpu.*freq" - 运行
watch -n 1 'cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq 2>/dev/null',每秒刷新一次,自动匹配所有在线核心 - 注意:
cpu*会包含超线程逻辑核;如果某核输出为空,可能是被isolcpus隔离,或已 offline(查cat /sys/devices/system/cpu/online)
cpupower monitor 是唯一能持续采样各核频率的工具
当你需要观察频率随负载波动的过程(比如跑 stress-ng --cpu 4 时各核是否同步升频),cpupower monitor 是不可替代的。它每秒输出一行,列明每个 cpu0、cpu1… 的当前频率(kHz),格式规整,适合重定向进日志做后续分析。
容易踩的坑:
- 必须 root 权限,且内核需启用
CONFIG_X86_ACPI_CPUFREQ或对应驱动(虚拟机中基本不可用) - 默认无时间戳,若要对齐其他指标(如温度、负载),得手动加
date前缀,例如:sudo stdbuf -oL cpupower monitor | while read line; do echo "$(date '+%s.%N') $line"; done - 输出里数值是 kHz,不是 MHz——别直接除以 1000 当成 GHz 看,先确认单位
别信 /proc/cpuinfo 的 cpu MHz 字段当实时值用
它确实每核一行,看起来像实时值,但实际由内核周期性缓存更新,有滞后性。尤其在频率快速切换(如 Turbo Boost 瞬间触发又回落)时,grep "cpu MHz" /proc/cpuinfo 可能卡在上一秒的状态。
常见误操作:
-
grep "cpu MHz" /proc/cpuinfo | head -n 1—— 只取第一个核心,完全忽略其余核的实际状态 - 把输出当绝对精度值:它显示
cpu MHz : 4200.000,但硬件寄存器此刻可能已是 4198.3 MHz,cpupower frequency-info --freq才更接近真实 - 没意识到这是瞬时值:空载时可能全核都是 800.000,一开编译就跳到 4000+,不能拿它当标称频率参考
turbostat 能同时看频率、C-state 和功耗,但权限和环境限制多
如果你要诊断“为什么睿频没起来”,turbostat 是首选:它每秒显示每核频率、包级功耗、C-state 深度、温度,还能告诉你是否受 RAPL 限频。命令如 sudo turbostat --interval 1。
关键限制:
- 报
No permission to change system clock不是权限问题,而是 TSC 校准失败,通常发生在某些云主机或老旧 BIOS 上 - 需要
msr内核模块加载(modprobe msr),部分容器环境或加固系统会禁用 - 输出字段多,初看容易混淆:
Avg_MHz是过去一秒平均,Bzy_MHz是忙时频率,TSC_MHz是基准时钟——别把后者当运行频率
scaling_cur_freq 显示 3200000,turbostat 的 Bzy_MHz 却是 4100,说明该核刚从空闲唤醒、还没来得及升频到位——这种细微差异,只靠一个命令永远抓不住。











