mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-03 10:14:44 +08:00
1.7 KiB
1.7 KiB
eBPF 入门实践教程:编写 eBPF 程序 Bitesize: 监控块设备 I/O
背景
为了能更好的获得 I/O 操作需要的磁盘块大小相关信息,Bitesize 工具被开发。它可以在启动后追踪 不同进程所需要的块大小,并以直方图的形式显示分布
实现原理
Biteszie 在 block_rq_issue 追踪点下挂在了处理函数。当进程对磁盘发出了块 I/O 请求操作时, 系统会经过此挂载点,此时处理函数或许请求的信息,将其存入对应的map中。
static int trace_rq_issue(struct request *rq)
{
struct hist_key hkey;
struct hist *histp;
u64 slot;
if (filter_dev) {
struct gendisk *disk = get_disk(rq);
u32 dev;
dev = disk ? MKDEV(BPF_CORE_READ(disk, major),
BPF_CORE_READ(disk, first_minor)) : 0;
if (targ_dev != dev)
return 0;
}
bpf_get_current_comm(&hkey.comm, sizeof(hkey.comm));
if (!comm_allowed(hkey.comm))
return 0;
histp = bpf_map_lookup_elem(&hists, &hkey);
if (!histp) {
bpf_map_update_elem(&hists, &hkey, &initial_hist, 0);
histp = bpf_map_lookup_elem(&hists, &hkey);
if (!histp)
return 0;
}
slot = log2l(rq->__data_len / 1024);
if (slot >= MAX_SLOTS)
slot = MAX_SLOTS - 1;
__sync_fetch_and_add(&histp->slots[slot], 1);
return 0;
}
SEC("tp_btf/block_rq_issue")
int BPF_PROG(block_rq_issue)
{
if (LINUX_KERNEL_VERSION >= KERNEL_VERSION(5, 11, 0))
return trace_rq_issue((void *)ctx[0]);
else
return trace_rq_issue((void *)ctx[1]);
}
当用户发出中止工具的指令后,其用户态代码会将map中存储的数据读出并逐进程的展示追踪结果
Eunomia中使用方式
总结
Bitesize 以进程为粒度,使得开发者可以更好的掌握程序对磁盘 I/O 的请求情况。