Linux进程级I/O统计:TASKSTATS_CMD_ATTR_TGID无法正常工作的问题
问题:如何获取进程所有存活及已终止线程的I/O统计(排除已终止子进程)
在Linux环境中,现有I/O统计接口存在以下局限,无法直接满足「获取进程自身所有存活+已终止线程的I/O、排除已终止子进程」的需求:
/proc/[pid]/io的read_bytes和write_bytes字段会包含已终止子进程的I/O数据,不符合统计范围要求- 汇总
/proc/[pid]/task/[tid]/io仅能获取当前存活线程的累计I/O,无法覆盖已终止的线程 taskstats接口的TASKSTATS_CMD_ATTR_TGID命令(按进程组tgid查询)实际无法返回I/O统计:Linux 6.3内核仅为单个线程(pid)的taskstats结构体填充I/O记账字段,getdelays -t(按tgid查询)也无法返回I/O数据,监听进程退出事件时同样如此
可行解决方案
1. 实时追踪线程生命周期,主动记录已终止线程I/O
- 实现思路:
- 利用
inotify监控/proc/[pid]/task/目录的变化,当有线程目录被删除时(对应线程终止),立即读取该线程的/proc/[pid]/task/[tid]/io数据,并入进程的总统计 - 同时定期读取当前存活线程的
/proc/[pid]/task/[tid]/io数据,汇总存活线程的I/O
- 利用
- 注意:该方案需要从进程启动时开始追踪,否则会遗漏启动前已终止线程的I/O数据
2. 使用eBPF工具汇总全生命周期线程I/O
- 实现思路:
- 编写eBPF程序,钩住内核中线程退出的关键函数(如
do_exit),在线程终止时直接读取task_struct内的ioacct相关统计字段,按进程tgid进行汇总存储 - 对于当前存活的线程,可通过eBPF遍历进程的线程列表,读取每个线程的I/O数据并累加
- 编写eBPF程序,钩住内核中线程退出的关键函数(如
- 优势:无需提前追踪,加载eBPF程序后可覆盖后续所有线程的退出事件,同时能获取当前存活线程的统计,适合对运行中进程进行统计
3. 自定义内核模块(仅推荐特殊场景)
- 若上述用户态方案无法满足需求,可编写内核模块,在内核层面维护按tgid汇总的、包含所有存活/已终止线程的I/O统计,并暴露用户态接口
- 劣势:需要修改内核逻辑,维护成本高,不适合通用场景
内容的提问来源于stack exchange,提问作者Irfan Latif
相关产品推荐
相关产品推荐

