read_bytes是唯一反映进程真实磁盘读取总量的字段,仅统计实际从块设备读入内存的字节数,不含缓存命中或伪设备读取;多次采样其差值即为某时段真实磁盘读量。

read_bytes 是唯一能反映进程真实磁盘读取总量的字段,它不包含缓存命中、终端输入或 /dev/zero 这类伪设备读取,只统计实际从块设备(如硬盘、SSD)拉进内存的字节数。
直接读 /proc/[pid]/io 获取实时读取总量
Linux 2.6.20+ 内核中每个进程的 /proc/[pid]/io 文件提供原始 I/O 统计。关键字段只有 read_bytes 值可信:
-
rchar是进程调用read(2)等系统调用传入的总长度,哪怕数据来自 page cache 或管道,也会被计入 —— 它不是磁盘读 -
read_bytes才是内核真正向块层发起的读请求字节数,对 ext4/xfs 等块设备文件系统准确;若进程只读内存映射文件(mmap)且未触发缺页,该值可能为 0 - 执行
cat /proc/1234/io | grep read_bytes即可提取当前值,单位是字节;多次采样差值即为某段时间内的真实磁盘读取量
用 iotop -a 查看累计读写(含历史趋势)
iotop 默认显示实时速率,但加 -a 参数后会累加自启动以来的总读写字节数,适合快速比对多个进程的历史 IO 消耗:
- 必须以 root 运行:
sudo iotop -a -o(-o只显示有 I/O 的进程,避免干扰) - 输出列中
DISK READ和DISK WRITE显示的是累计字节数(不是 B/s),单位自动缩放为 B/K/M/G - 注意:该累计值在
iotop进程重启后归零,不跨会话持久化;它底层也是轮询/proc/[pid]/io,所以和手动读取read_bytes本质一致
没有真正的“IO 历史记录”——所有数据都是快照或累计
Linux 内核本身不保存进程 I/O 的时间序列日志。所谓“历史”,只能靠外部工具持续采集快照并自行存储:
- 不要指望
dmesg或journalctl里有进程级 IO 历史 ——vm.block_dump=1虽能打日志,但只记录块层事件(如 “WRITE block 12345 on sda”),无法关联到具体进程名,且开销极大、格式难解析,生产环境禁用 - 如果需要长期追踪,得自己写脚本周期性抓取
/proc/[pid]/io并写入文件,例如:while true; do echo "$(date +%s),$(cat /proc/1234/io 2>/dev/null | awk '/read_bytes/ {print $2}')"; sleep 5; done >> io.log -
pidstat -d 5(来自 sysstat)可输出带时间戳的每秒 IO 报告,但它底层仍是采样/proc/[pid]/io,且默认只保留最近一次差值,不保存原始快照
真正容易被忽略的是:即使你拿到 read_bytes 的两个时间点差值,它也只代表“内核向块设备发出的读请求量”,不等于物理磁盘实际读取量(比如 RAID 层可能合并、重排请求),更不等于应用逻辑上“读了多少业务数据”。要定位问题,永远先确认这个数字是否异常高,再结合 lsof -p [pid] 看它在读哪些文件。











