简介:面向Linux/Unix系统管理员与开发者的Intel处理器性能监控资源,提供turbostat工具的核心C语言源代码。turbostat是一款命令行实用程序,能够实时显示CPU在Turbo Boost动态加速下的工作频率变化,并统计各C-state(C0、C1、C3等)状态下的驻留时间,帮助定位系统响应延迟、功耗异常等问题,适合正在学习系统性能调优或底层硬件交互的读者。资源包仅含1个C源码文件,压缩后约13KB,体量精简,便于直接阅读、修改和编译测试。通过分析turbostat.c,可掌握如何借助sysfs、procfs虚拟文件系统读取CPU核心状态,调用性能计数器(PMU)采集频率与功耗数据,并理解Linux用户态程序与内核交互的典型代码组织方式。该资源已有293人学习下载,对希望理解现代处理器节能机制、优化应用程序运行效率的开发者来说,是一份简洁实用的参考资料。
1. turbostat 解决什么问题:一款能看到 CPU 真实频率与功耗的命令行工具
如果你的服务器负载不高却频闪 CPU 温度告警,先别急着换散热,turbostat 多半能在一分钟内给出答案。它来自 Linux 内核源码树,是 Intel、AMD x86 平台上的频率、C-state 与功耗观测工具,能直接读出每个物理核心当前跑在多少 MHz、停留在哪种 C-state、整颗 CPU 的封装功耗是多少瓦。top 和 mpstat 只能看到逻辑 CPU 的占用率,看不透频率、温度、功耗这三件事;turbostat 恰好把这三件事展平在终端里。命令行里拿到一个带 .rar 后缀的包,说明你手里的可能是别人打包好的源码或编译产物,解开、编译、装好之后,就能在自己的 Unix/Linux 机器上复现下面的所有操作。适合运维排查“CPU 明明没跑满却发烫”、内核开发者验证调频策略、以及想搞清楚笔记本续航去哪了的桌面用户。
2. turbostat 输出字段与 MSR 读取原理
2.1 为什么 turbostat 需要 root 权限
turbostat 的数据来源不是 /proc/stat,而是直接读取 CPU 的 MSR(Model Specific Register)。MSR 是 x86 架构里一组用于控制电压、频率、功耗、性能计数器的寄存器,读写它们需要特权指令。以常见的 Intel 平台为例:
- 实际频率通过 APERF(MSR 0xE8)和 MPERF(MSR 0xE7)两个计数器换算。MPERF 按 TSC(恒定时间戳计数器)递增,APERF 按 CPU 当前实际频率递增,两者比值乘以 TSC 频率就是真实运行频率。turbostat 的 Bzy_MHz 字段就是这么算出来的。
- C-state 驻留时间分布在多组 MSR 里,典型地址在 MSR_CORE_C1_RESIDENCY(0x60C)到 MSR_PKG_C10_RESIDENCY 之间,随 CPU 代际不同而不同。
- RAPL(Running Average Power Limit)域功耗通过 MSR 0x610(PKG)、0x611(PP0)、0x613(DRAM)等寄存器读取。
这套机制延续了 Unix 时代直接面对硬件、用最小代价拿最真实数据的传统,跟 Ken Thompson、Dennis Ritchie 那批人做系统工具的思路一脉相承。现代 Linux 对 MSR 读取做了权限管控,只有 root 或具有 CAP_SYS_RAWIO 能力的进程才能访问 /dev/cpu/0/msr,所以裸跑 turbostat 通常会看到 Operation not permitted。
2.2 一份典型输出逐行看
在装有 turbostat 的机器上执行:
sudo turbostat -i 1 -n 1得到类似下面的输出(字段数量取决于 CPU 型号和 turbostat 版本):
CPU Core CPU% Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CoreTmp PkgTmp PkgWatt - - 3.21 5.64 2985 2400 1.43 9.82 82.71 54 56 68.40 0 0 2.18 4.13 3010 2400 1.20 8.55 85.77 52 54 - 1 1 4.31 6.22 2940 2400 1.81 9.03 80.12 55 56 -CPU是逻辑 CPU 编号,Core是它所属的物理核心编号,虚拟化或超线程场景下两者会明显不同。CPU%表示该逻辑 CPU 上所有任务占用时间占比,Busy%表示该逻辑 CPU 处于非空闲状态的时间占比。两者差异来自对“空闲”的定义:CPU% 按调度器统计,Busy% 按 turbostat 采样的中断/空闲比例计算。Bzy_MHz是采样窗口内的实际运行频率,TSC_MHz是恒定 TSC 频率。如果 Bzy_MHz 明显低于标称基频,说明处于降频或 C-state 节能状态;长时间接近睿频上限则说明负载确实吃满。CPU%c1、CPU%c3、CPU%c6是核心在各 C-state 的驻留时间比例。c1 是停机状态,c3/c6 会关闭 PLL 或缓存电源,延迟随之增大。CoreTmp和PkgTmp分别是核心温度和封装温度,单位摄氏度;PkgWatt是整颗 CPU 封装功耗。
首次运行建议加--debug看完整探测信息,它会列出 CPU 型号、max turbo 频率、MSR 偏移和 RAPL 域支持情况,这些信息在排错时非常有用:
sudo turbostat --debug -i 1 -n 1 | head -40这里-i 1表示每秒采样一次,-n 1表示只输出一轮,head -40截断前 40 行。--debug会打印探测到的 MSR 地址范围,可以用来确认当前 CPU 是否支持 C8/C10 等深度节能状态。如果输出里看不到 PkgWatt 列,先检查内核模块 msr 是否已加载。
3. 从 .rar 包解压、编译并安装 turbostat
3.1 解开 .rar:两个坑位提前避开
turbostat 本身不叫 .rar,但标题既然给了这种分发形式,就按拿到一个压缩包来处理。Linux 下解压 .rar 不能靠 unzip,常见做法是安装 unrar-free 或 unar。Debian/Ubuntu 系执行:
sudo apt update sudo apt install unrar-free unar unar turbostat.rar -o ./turbostat-srcunar对中文文件名的处理比 unrar-free 稳妥,能够自动识别 GBK 或 UTF-8 编码,避免解压之后出现“linux 解压文件乱码”的情况。这一步之后,进入解压出的目录确认内容:
cd turbostat-src ls -la file *这里的file *用来快速判断包里是源码目录、单二进制文件还是带 Makefile 的工程。很多打着 .rar 旗号分发的内核小工具,实际只是把编译好的二进制和依赖库打了个包,直接解开就能跑;如果看到 turbostat 和 windrv 之类的文件,先chmod +x再试运行。
3.2 源码编译:依赖与 Makefile 参数
如果你拿到的是源码,通常包含 Makefile、turbostat.c 和 msr.h。turbostat 依赖 libcap 来获取 Capability 支持,编译前需要安装开发头文件:
sudo apt install libcap-dev build-essential makeMakefile 里常见可调参数包括CC、CFLAGS、DESTDIR和PREFIX。例如指定交叉编译器或调整优化级别:
make CC=gcc CFLAGS="-O2 -Wall" sudo make install DESTDIR=/usr/local PREFIX=/usr/localDESTDIR主要用于打包场景,把安装路径重定向到临时目录;普通机器上直接sudo make install即可。如果 Makefile 里没有 install 目标,就把编译出的 turbostat 复制到 /usr/local/bin:
sudo cp turbostat /usr/local/bin/ turbostat --version验证安装成功的标志是能打印版本号。注意 turbostat 从 2010 年进入内核源码树以来,后续版本陆续加入了 RAPL、AMT、--show/--hide 等特性,老版本可能缺少新参数,遇到Unknown option时优先考虑升级源码而不是降级用法。
3.3 内核源码树里的替代编译路径
内核源码自身也带了一份 turbostat,路径在tools/power/x86/turbostat/。如果 .rar 包解出来不完整,可以直接从内核源码编译:
cd /usr/src/linux/tools/power/x86/turbostat make sudo make install这个路径依赖内核头文件,编译前先确认/lib/modules/$(uname -r)/build符号链接存在。从内核树编译的好处是版本与当前内核严格匹配,MSR 偏移表覆盖完整;坏处是如果你的发行版内核源码没装全,需要先sudo apt install linux-headers-$(uname -r)。注意这里装的头文件可能只有模块使用的部分,完整源码编译通常建议克隆一份内核仓库或者用发行版提供的apt-get source linux。
4. turbostat 常用参数与三个高频排查场景
4.1 参数表:先知道调什么
turbostat 的参数体系分三类:采样控制、输出过滤、显示格式。下表是实际工作中用得最多的组合:
| 参数 | 作用 | 常用搭配 |
|---|---|---|
-i 秒 | 采样间隔,默认 5 秒 | -i 1适合短时压测 |
-n 次数 | 采样轮数,默认无限 | -n 3适合脚本调用 |
-c CPU列表 | 只监控指定逻辑 CPU | -c 0-3,8-11 |
-p | 仅显示物理核心 | 配合-c使用 |
-S | 不显示空闲核心行 | 多核机器减少刷屏 |
--show 字段 | 只输出指定列 | --show PkgWatt,PkgTmp |
--hide 字段 | 隐藏指定列 | --hide RAMWatt |
-q | 安静模式,去掉顶部表头 | 脚本解析用 |
--num_iterations | 等价于-n,长选项更可读 | 配合-i |
-T | 指定温度传感器路径 | 特殊平台用 |
--show和--hide是脚本化最关键的参数,能用它们把输出裁剪成固定列数,awk 解析就不容易错位。另外-o 文件可以把输出重定向到文件,等价于 shell 的>但不会截断表头。
4.2 场景一:追踪某个进程所在 CPU 的频率抖动
排查 Java 服务响应变慢时,常见现象是 CPU 占用不高但延迟毛刺明显。先用taskset或pidstat找到进程所在逻辑 CPU,比如 PID 1234 跑在 CPU 2 和 3 上,然后单独盯这两颗核心:
sudo turbostat -c 2,3 -i 1 --show CPU,Busy%,Bzy_MHz,CoreTmp观察 Bzy_MHz 是否周期性跌落。如果频率从 3.8GHz 掉到 2.4GHz 又弹回去,多半是功耗墙(RAPL)或温度墙触发降频,此时--show PkgWatt,PkgTmp能补上最后一环:
sudo turbostat -c 2,3 -i 1 --show CPU,Bzy_MHz,PkgWatt,PkgTmp-c 2,3限定监控范围,--show保证每一轮输出只有四列。PkgWatt 接近 PL1 功耗限制(通常 65W 或 125W)时,降频原因基本锁定在功耗,而不是散热。
4.3 场景二:检查 C-state 是否异常导致功耗偏高
服务器空载却比满载还费电,问题往往出在 C-state:驱动或固件把核心钉在 C0/C1,深度节能状态进不去。用下面的命令看驻留比例:
sudo turbostat -S -i 5 --show CPU,CPU%c1,CPU%c3,CPU%c6,PkgWatt-S跳过全空闲核心,CPU%c6在空载时应占绝大多数。如果 c6 几乎为 0 且 c1 接近 100%,说明有驱动频繁唤醒核心,典型元凶是网卡中断、USB 轮询或者定时器过快。配合powertop --auto-tune调整后,再用同样命令复测,c6 比例升上来就说明修复到位。这个场景也常出现在“linux 面试题”里,考察点就是你能不能把驻留时间柱状图翻译成实际问题。
4.4 场景三:验证 cpufreq 调优效果
切换 CPU 调频策略后,turbostat 是最直观的验收工具。把 conservative 和 performance 两种 governor 下的数据各采一分钟:
sudo cpupower frequency-set -g conservative sudo turbostat -i 2 -n 30 --show Busy%,Bzy_MHz,PkgWatt > conservative.log sudo cpupower frequency-set -g performance sudo turbostat -i 2 -n 30 --show Busy%,Bzy_MHz,PkgWatt > performance.log paste conservative.log performance.log | awk '{print $1, $2, $4}'这里-n 30配合-i 2采样 60 秒,日志文件用 shell 重定向保存。paste 命令把两份输出并排粘在一起,awk 打印 Busy%、Bzy_MHz、PkgWatt 三列,方便对比同负载下两种策略的能耗差。如果 conservative 的 Bzy_MHz 明显偏低但 PkgWatt 没有下降,说明频率降了但电压没跟着降,问题在硬件或固件而不是内核调频策略。
5. 把 turbostat 接入监控脚本:告警与调优验证
5.1 一个可落地的 bash 监控循环
手动跑 turbostat 只适合排查,持续监控要交给脚本。下面这段脚本每 10 秒采样一次,用 awk 从-q模式的输出里抓 PkgWatt 和 PkgTmp,超阈值就写入日志:
#!/usr/bin/env bash THRESHOLD_POWER=80 THRESHOLD_TEMP=85 LOG=/var/log/turbostat-monitor.log while true; do sudo turbostat -q -i 10 -n 1 --show PkgWatt,PkgTmp | tail -1 | while read -r PWR TMP; do if [ "$PWR" -gt "$THRESHOLD_POWER" ] || [ "$TMP" -gt "$THRESHOLD_TEMP" ]; then echo "$(date +%F_%T) WARN power=$PWR temp=$TMP" >> "$LOG" fi done sleep 10 donesleep 10与-i 10各自守一道间隔:turbostat 自己采样 10 秒,循环再等 10 秒,保证两个采样窗口不重叠。-q去掉表头,tail -1取最后一行数据,read 按空白字符拆分成 PWR 和 TMP 两个变量。注意 while read 里的管道子 shell 会有变量作用域问题,需要把日志追加操作放在管道内完成,这也是刻意写成 echo 直接进 LOG 的原因。如果不想每次循环都 sudo,可以对 turbostat 所在二进制设置 CAP_SYS_RAWIO:
sudo setcap cap_sys_rawio=ep /usr/local/bin/turbostat设置之后普通用户就能直接跑,适合放在共享监控机上。不过 setcap 在部分老内核或容器环境不生效,容器里还要额外检查 /dev/cpu/0/msr 是否被映射进容器。
5.2 用 numactl 压测验证 NUMA 拓扑下的功耗分布
多路服务器上不同 NUMA 节点的 CPU 功耗往往不均衡,turbostat 默认按全局聚合输出,需要按节点拆开看。先确认 NUMA 拓扑:
numactl --hardware假设 node0 对应 CPU 0-15,node1 对应 CPU 16-31,压测时绑定到 node0:
numactl --cpunodebind=0 --membind=0 stress-ng --cpu 16 --timeout 60s & sudo turbostat -c 0-15 -i 5 --show Core,PkgWatt,CoreTmp第一行是 numa 绑定压测命令,第二行采集前半段数据;压测结束后再采一次空闲数据,对比 node0 和 node1 的 PkgWatt 差值。如果绑定 node0 但 node1 的功耗也在涨,说明内存控制器或 QPI/UPI 链路成了热点,这在 NUMA 调优时是常见结论。turbostat 在输出里不会标 NUMA 节点,需要靠-c参数手动限域,这个细节比单纯看全局功耗更有价值。
5.3 与 systemd 集成:开机自动记录基线
把上面脚本包装成 systemd 服务可以记录每次开机后的功耗基线,长期数据用来判断硅脂老化或散热器积灰。写一个 unit 文件 /etc/systemd/system/turbostat-monitor.service:
[Unit] Description=Turbostat power monitor After=multi-user.target [Service] ExecStart=/usr/local/bin/turbostat-monitor.sh Restart=on-failure RestartSec=30 [Install] WantedBy=multi-user.target启动命令sudo systemctl daemon-reload && sudo systemctl enable --now turbostat-monitor。服务里不需要写 User=root,因为脚本内部已经用 sudo 或 setcap 解决权限;但如果用 sudo 方式,注意 systemd 默认不带 tty,需要把 NOPASSWD 配好或者干脆用 setcap。这套方案适合作为 linux 常用命令之外的常驻守护,毕竟 turbostat 这类工具的强项是一次性观测,持续采样交给服务更省心。
6. turbostat 常见报错与验证技巧
6.1 三种常见失败的处理顺序
Operation not permitted:先sudo modprobe msr加载 MSR 模块,再检查/dev/cpu/0/msr是否存在。容器和部分云主机即使有 root 也访问不了 MSR,因为宿主机没把设备透传进来,此时改用turbostat --debug确认设备枚举结果。turbostat: no /dev/cpu/0/msr:内核配置没开 CONFIG_X86_MSR,需要重新编译内核或换发行版提供的内核。- 输出全部是 0.00:虚拟化平台一般拿不到真实 MSR 数据,常见于 VMware/KVM 虚拟机。属于预期行为,不是安装失败。
6.2 输出校验:手工算一遍 Bzy_MHz
turbostat 算出 Bzy_MHz 的逻辑可以用一个小脚本验证,避免工具本身出问题。读取 APERF 和 MPERF 两次,差值乘上 TSC 频率再取均值:
sudo rdmsr -d 0xE8 && sudo rdmsr -d 0xE7 && sleep 1 && sudo rdmsr -d 0xE8 && sudo rdmsr -d 0xE7rdmsr 来自 msr-tools 包,需要先sudo apt install msr-tools。得到四个十进制数后,实际频率近似为(APERF2 - APERF1) / (MPERF2 - MPERF1) * TSC_MHz。拿这个结果对比 turbostat 输出,误差在 1% 以内说明 MSR 换算链路正常;误差过大说明 TSC 频率读错,多见于老款 Atom 或 BIOS 设置了不标准的 TSC。平时可以把turbostat -q -i 1 -n 1 --show Bzy_MHz直接写成 shell 别名alias freq='sudo turbostat -q -i 1 -n 1 --show Bzy_MHz',加进 .bashrc,随时确认当前频率区间。
本文还有配套的精品资源,点击获取