Linux blktrace
blktrace 是 Linux 块层 I/O 跟踪的工具,结合内核中的 blk_trace 接口实现对块设备 I/O 操作进行高精度事件跟踪。它可以精确分析 I/O 请求从生成到完成的全过程,广泛用于磁盘性能分析、存储系统调优等场景。
架构概览
blktrace 工具依赖以下几个核心组件:
- 内核支持 (
CONFIG_BLK_DEV_IO_TRACE)
- 开启块层 I/O 跟踪机制,内核会将块层事件写入 ring buffer。
- 内核模块:
blk-core.c,blk-sysfs.c等
- 实现了 tracing buffer 分配、事件记录、hook 安装等。
- 用户态工具:
blktrace,blkparse,btt
blktrace: 收集内核 trace 数据;blkparse: 解析 trace 数据;btt: 分析和统计输出。
工作流程
- 用户启动 blktrace
blktrace -d /dev/sdX -o trace
- blktrace 发起 ioctl:
BLKTRACESETUP
- 打开 /dev/sdX,调用 ioctl(fd, BLKTRACESETUP, &blk_user_trace_setup);
- 这会在内核中为设备创建一个 blk_trace 实例,分配 ring buffer,并注册事件钩子。
- 内核 hook 点记录事件
块层定义了一组 hook 点用于记录事件,例如:
blk_add_trace_bio():请求提交(Q);blk_add_trace_bio_complete():请求完成(C);blk_add_trace_rq_insert():请求插入队列(I);blk_add_trace_rq_issue():请求发送(D);blk_add_trace_rq_complete():请求完成(C);
这些 hook 被自动注入到 block I/O 路径中(如 __blk_mq_issue_directly, blk_mq_start_request)。
- 事件写入 ring buffer
- 每个事件由
struct blk_io_trace表示; - ring buffer 是 per-CPU 的,避免锁竞争。
- blktrace 用户态读取 ring buffer
- 使用
mmap()将 ring buffer 映射到用户态; blktrace持续读取事件并写入日志文件;- 每个事件包括时间戳、PID、事件类型、扇区、长度等信息。
- blkparse 解析日志
blkparse -i trace.blktrace.* -o - | less
- 分析每个 I/O 请求的生命周期。
事件类型(blk_io_trace->action 字段)
| 事件代码 | 含义 | 描述 |
|---|---|---|
| Q | Queue | 请求被创建并进入 I/O 队列 |
| M | Merge | 请求合并 |
| I | Insert | 插入调度队列 |
| D | Issue | 请求被发往设备 |
| C | Complete | 请求完成 |
| B | Bounce | 内存页 bounce 操作(如高端内存) |
| A | Remap | 映射(如 dm、md 中映射到底层设备) |
ring buffer 实现原理
每个 CPU 有一个 blk_trace 实例,它包含:
struct blk_trace {
struct percpu_data *pcpu;
...
};
struct percpu_data {
void *buffer; // trace ring buffer
unsigned int head, tail; // ring buffer 指针
};
- 内核使用
__trace_note_message()将事件写入 buffer; - 如果 buffer 满,事件会丢弃并计数;
blktrace工具使用mmap()映射 buffer,轮询读取数据。
blktrace 和 ftrace/perf/bpf 区别
| 工具 | 层级 | 能力 | 优势 |
|---|---|---|---|
| blktrace | 块层 | 精确跟踪块设备 I/O | 粒度细,可计算 IO 延迟路径 |
| ftrace | 内核函数 | 函数级 tracing | 通用性强 |
| perf | 硬件/内核 | 事件采样+统计分析 | 全面,适合性能瓶颈分析 |
| eBPF | 任意 hook | 动态 tracing 与统计 | 灵活、低开销,可附加逻辑处理 |
典型应用场景
- 评估 I/O 调度器(如 BFQ, MQ)效率;
- 分析数据库 / 文件系统 I/O 延迟瓶颈;
- 监控随机与顺序读写行为;
- 分析合并、插入延迟、issue 到 complete 时间等。
关键源码路径(以 Linux 6.x 为例)
| 模块 | 说明 | 关键文件 |
|---|---|---|
| 核心定义 | blk_io_trace, blk_trace | include/linux/blktrace_api.h |
| 内核实现 | trace buffer 实现等 | block/blk-core.c, block/blk-sysfs.c |
| ioctl 接口 | 与 blktrace 用户通信 | block/ioctl.c (BLKTRACE*) |
示例分析
以下是 blkparse 输出的 I/O 请求生命周期:
8,0 1 1 0.000000000 1 Q WS 0 + 8 [bash]
8,0 1 2 0.000000500 1 M WS 0 + 8 [bash]
8,0 1 3 0.000001000 1 I WS 0 + 8 [bash]
8,0 1 4 0.000002000 1 D WS 0 + 8 [bash]
8,0 1 5 0.000010000 1 C WS 0 + 8 [bash]
表示:
- 请求 1 被创建(Q);
- 被合并(M);
- 插入队列(I);
- 发往设备(D);
- 最终完成(C);
- 时间差可用于计算延迟。
总结
blktrace是 Linux 块层的原生跟踪机制;- 通过内核 hook 捕捉 I/O 事件并通过 mmap 提供用户态访问;
- 适用于深入分析存储路径延迟瓶颈;
- 与 ftrace/perf/eBPF 相辅相成,适用于不同层级。
7373

被折叠的 条评论
为什么被折叠?



