Linux 性能实战 | 第 3 篇 CPU 使用率的八种状态拆解
本文深入解析CPU使用率的八种状态(us/sy/ni/id/wa/hi/si/st),帮助精准定位性能瓶颈。通过工具如top、mpstat等获取这些指标,重点分析了iowait(wa)的本质是CPU空闲状态而非忙碌状态,并给出诊断iowait的三步法。文章结合实际案例,如自动驾驶数据录制模块的iowait优化方案,以及网络摄像头导致软中断(si)飙升的问题,说明如何通过状态拆解来对症下药。最后强调
第三章|CPU 使用率的八种状态拆解
来源:《Linux 性能实战系列》· 第3篇
适用场景:智能驾驶域控制器 | ECU性能分析 | 仿真平台线上问题排查
在第二章中,我们已经明确了一件事:Load Average 反映的是 R + D 状态的“排队压力”,而不是 CPU 使用率本身。
但当我们确认 “Load 高,确实是 CPU 忙导致的” 之后,真正的问题才刚开始:
CPU 到底在忙什么?
这一章,我们不再笼统地谈“CPU 利用率”,而是把 CPU 的时间拆成八种状态,一步步定位:是业务代码在跑?是内核在忙?还是中断、I/O 在偷偷吃掉算力?
我们把 CPU 时间切成八个状态,精确定位"忙在用户态、内核态、还是中断处理",建立细粒度的观测能力。
为什么需要拆解 CPU 状态?
常见误区:看到 CPU 利用率 80%,就认为"系统很忙"。
实际情况可能是:
- 80% 都在
wa(iowait)→ CPU 在等 IO,实际计算很少。 - 80% 都在
si(软中断)→ 网络包处理压力大,业务代码没跑多少。 - 80% 都在
sy(内核态)→ 系统调用频繁,可能有锁竞争。
不拆解状态,就无法对症下药。
CPU 时间的“八种口味”:us/sy/ni/id/wa/hi/si/st
CPU 的时间就像一块蛋糕,可以被切成不同部分,分配给不同类型的任务。理解这些“口味”的比例,是诊断性能问题的关键。我们可以通过 top、mpstat -P ALL 1 或 sar -P ALL 1 5 等工具轻松获取这些值。
| 状态 | 名称 | 描述 | 自动驾驶场景举例 |
|---|---|---|---|
| us | User | 用户态:执行应用程序代码的时间。 | 感知算法(如 YOLO、Lidar 点云处理)、规划决策、SOME/IP 序列化。 |
| sy | System | 内核态:执行系统调用、处理中断、管理内存等内核任务的时间。 | 频繁的文件读写(录包)、网络发包(SOME/IP)、进程间通信。 |
| ni | Nice | 低优先级用户态:nice 值调整过的进程所消耗的时间。 |
后台的日志压缩、数据清洗等非实时任务。 |
| id | Idle | 空闲:CPU 没有任务可执行的时间。 | 系统负载低,资源充足。 |
| wa | I/O Wait | 等待 I/O:CPU 等待块设备(如磁盘)I/O 操作完成的时间。 | 等待摄像头数据写入磁盘、等待模型文件加载。注意:此时 CPU 是空闲的。 |
| hi | Hardware IRQ | 硬中断:处理硬件设备(如网卡、定时器)中断请求的时间。 | 网卡收到数据包、CAN 卡接收报文、GPS 的 PPS 秒脉冲信号。 |
| si | Software IRQ | 软中断:为分担硬中断压力而延迟处理的任务。 | 网络数据包的协议栈处理(ksoftirqd 进程)、块设备 I/O 的后续处理。 |
| st | Steal | 被窃取:在虚拟化环境中,被宿主机(Hypervisor)分配给其他虚拟机的时间。 | 在多 VM 环境中,本 VM 的 CPU 资源被抢占。 |
这些状态共同构成了 CPU 100% 的时间。一个更直观的关系图如下:
这个图清晰地划分了 CPU 忙碌 和 CPU 空闲 两大阵营。特别要注意,wa(I/O Wait)虽然名字里有 “Wait”,但它属于 CPU 空闲时间。这是最常见的误区之一,我们稍后会深入探讨。
关键指标深入分析
1. iowait 的再审视:CPU 真的在“等”吗?
这是 Linux CPU 指标中最容易被误解的一个。
核心纠正:iowait 本质上是 CPU 的一种 空闲 状态。 它衡量的是 CPU 既没有其他任务可执行,又恰好有至少一个任务正在等待块设备 I/O(如磁盘) 的时间比例。
-
wa高意味着什么?- 真正含义:系统中有 I/O 压力,并且在 I/O 等待期间,CPU 没有其他计算任务(R 状态进程)来“填补空白”。
- 常见误解:
wa高 = 磁盘慢。虽然有关联,但wa高也可能是因为同步 I/O 请求过多,即使磁盘性能正常,CPU 也会因为“没事做”而累积wa时间。
-
wa不高,但load很高?- 这是另一个经典场景。
load由 R 状态和 D 状态进程贡献。如果大量进程处于 D 状态,但等待的不是块设备 I/O(例如,等待网络、进程间锁),那么load会飙升,但wa可能很低。
- 这是另一个经典场景。
诊断 iowait 的三步法:
-
确认 I/O 压力: 使用
iostat -x 1或sar -d 1。r/s,w/s:每秒读写请求数。await:平均每次 I/O 请求的等待时间(包括队列和设备处理)。await显著增大是 I/O 瓶颈的强信号。avgqu-sz:平均请求队列长度。如果持续很高,说明 I/O 设备已经饱和。%util:设备利用率。接近 100% 表明设备非常繁忙。
-
定位等待 I/O 的进程: 使用
pidstat -d 1。- 这个工具能直接显示出哪些进程正在产生 I/O,以及它们的读写速率。
-
检查 D 状态进程: 使用
ps -aux | grep ' D'或top。- 查看
wchan(Wait Channel) 列,了解进程具体在等待哪个内核函数,例如io_schedule、page_fault等。
- 查看
2. 案例:iowait 50% 的自动驾驶数据录制模块
场景:一个自动驾驶测试车在路采时,系统周期性卡顿,top 显示 wa 指标高达 50%。
分析过程:
-
iostat -x 1:发现/dev/sda(数据盘)的%util接近 100%,await时间超过 500ms,avgqu-sz持续大于 10。结论:磁盘 I/O 达到瓶颈。 -
pidstat -d 1:定位到data_recorder进程有大量的写操作(kB_wr/s极高)。 -
代码审查:发现
data_recorder模块为了保证数据不丢失,对每一帧传感器数据(如 Lidar)都执行了同步写入(O_SYNC标志或每次write后调用fsync)。这种设计在数据量大时会给磁盘带来巨大压力。
解决方案:
- 应用层优化:将同步写改为异步写。数据先写入内存缓冲区(Buffer),由一个独立的线程批量写入磁盘。这样可以将多次小的 I/O 合并为一次大的 I/O,大幅提升效率。
- 系统层优化:
- 更换硬件:改用更高性能的 NVMe SSD。
- 文件系统调优:调整文件系统的
commit间隔,或调整脏页回写(dirty pages writeback)相关的内核参数(/proc/sys/vm/dirty_*),让系统更平滑地刷盘,避免 I/O 突刺。 - 任务分离:如果可能,将数据录制任务绑定到独立的 CPU 核心和 I/O 控制器,避免与其他关键任务(如感知、规划)争抢资源。
3. 硬中断 (hi) 与软中断 (si):系统响应的“快车道”
中断是系统处理外部事件的核心机制,但如果处理不当,就会成为性能瓶颈。
-
hi(Hardware IRQ):硬中断,由硬件设备(如网卡、键盘、定时器)直接触发。它的优先级非常高,会立即打断当前 CPU 上正在执行的任务。硬中断处理程序(ISR, Interrupt Service Routine)被设计为尽可能快地执行,因为它会“冻结”其他所有操作。 -
si(Software IRQ):软中断,也称为“下半部”(Bottom Half)。它是为了分担硬中断的压力而设计的。硬中断处理程序在完成最紧急的操作后(例如,将网卡的数据拷贝到内存),会触发一个软中断,然后快速退出。剩余的大部分处理工作(例如,将数据包送往协议栈)则由软中断在稍后的、更合适的时机完成。常见的软中断处理由内核线程ksoftirqd/cpu_id执行。
为什么 si 过高是常见问题?
因为大量的网络、存储 I/O 都会触发软中断。如果软中断任务过重,ksoftirqd 进程会持续占用大量 CPU,导致用户态的应用程序(us)无法获得足够的 CPU 时间,表现为“系统 CPU 使用率高,但业务上不去”。
4. 案例:网络摄像头导致的 si 飙升
场景:在一个 ADAS 系统中,接入一个新的高分辨率摄像头后,top 显示某个 CPU 核心的 si 持续在 80% 以上,导致图像处理应用丢帧。
分析过程:
-
mpstat -P ALL 1:确认了 CPU3 的si使用率异常高。 -
cat /proc/interrupts:观察中断号的变化速率。发现与eth0网卡相关的中断计数在 CPU3 上飞速增长。这表明来自摄像头的网络流量都集中到了 CPU3 上。# watch -d 'cat /proc/interrupts' CPU0 CPU1 CPU2 CPU3 ... 110: 0 0 0 8934521 IR-IO-APIC eth0 ... -
cat /proc/softirqs:观察软中断计数。发现NET_RX(网络接收)在 CPU3 上增长最快。这进一步确认了瓶颈在于网络数据包的接收处理。
解决方案:
-
开启并配置 RPS (Receive Packet Steering):RPS 是一个纯软件的解决方案,它允许内核将网络数据包的处理(软中断
si)分发到多个 CPU 核心,即使物理网卡只将硬中断(hi)发送到单个核心。# echo f > /sys/class/net/eth0/queues/rx-0/rps_cpusf是一个位掩码,代表1111,表示允许将软中断分发到 CPU0-CPU3。 -
配置 IRQ 亲和性 (IRQ Affinity):如果网卡支持多队列(RSS, Receive Side Scaling),可以直接将硬件中断分发到多个 CPU 核心,从根源上解决单点瓶颈。
# echo 2 > /proc/irq/110/smp_affinity2的二进制是0010,表示将这个中断绑定到 CPU1。通过为不同队列设置不同的smp_affinity,可以将中断压力均摊。
诊断流程总结:从全局到根源
面对一个 CPU 使用率高的问题,可以遵循以下步骤进行拆解:
-
全局观察 (
top,uptime):- 先看
load average,判断系统负载压力。 - 再看
top的 CPU 状态行,对us,sy,wa,si等有初步印象。
- 先看
-
多核细节 (
mpstat -P ALL 1):- 查看每个核心的 CPU 状态。是否存在某个核心“一核有难,八方围观”?单核瓶颈(如
si过高)和多核瓶颈(如us普遍高)的排查方向完全不同。
- 查看每个核心的 CPU 状态。是否存在某个核心“一核有难,八方围观”?单核瓶颈(如
-
专项分析:
us/sy高:CPU 正在忙于计算。使用perf top或pidstat -u 1定位到具体的热点进程和函数。wa高:CPU 在闲等 I/O。使用iostat -x 1和pidstat -d 1定位 I/O 瓶颈设备和进程。hi/si高:中断压力大。使用cat /proc/interrupts和cat /proc/softirqs结合mpstat定位中断来源和不均衡问题。
-
深度钻取 (
perf record):- 对于复杂的内核态或用户态热点,使用
perf record -g抓取调用栈,生成火焰图,可以清晰地看到函数调用关系和耗时分布。
- 对于复杂的内核态或用户态热点,使用
小结
- CPU 的八种状态是进行性能诊断的“地图”,它指导我们从哪里入手。
iowait是 CPU 的空闲时间,高wa意味着“CPU 想干活但没得干,同时有任务在等磁盘”。hi和si是系统响应的关键路径,si过高通常与网络/存储 I/O 处理不均衡有关,需要通过中断绑核、RPS/RSS 等手段进行优化。- 掌握
mpstat,iostat,pidstat和perf等工具的组合使用,是建立 CPU 性能问题“直觉”的必经之路。
下一篇预告
下一章,我们将深入探讨进程的生命周期,特别是神秘的 D 状态(不可中断睡眠),揭示它与 load average 和 iowait 之间千丝万缕的联系。

更多推荐

所有评论(0)