使用 libbpf 编写 BPF 应用程序进阶技巧
本文地址:https://www.ebpf.top/post/top_and_tricks_for_bpf_libbpf
原文地址:https://www.pingcap.com/blog/tips-and-tricks-for-writing-linux-bpf-applications-with-libbpf/
2020 年初,当使用 BCC 工具分析我们数据库性能瓶颈并从 GitHub 上拉取代码时,我意外地发现 BCC 项目中额外多出了一个 libbpf-tools目录。我学习了 BPF 可移植性和 BCC 到 libbpf 转换文章,并且根据所学知识将之前提交的 bcc-tools 转换为了 libbpf-tools。最后,我完成了近 20 个工具的转换工作(参见 为什么我们将 BCC-Tools 转换为 libbpf-tools 用于 BPF 性能分析)。
在此过程中,我有幸得到了 Andrii Nakryiko(libbpf + BPF CO-RE 项目的负责人)的大量帮助。这是一段有趣的经历,我也学到了很多。在本文中,我将分享我在使用 libbpf 编写 BPF 程序方面的经验。我希望本文能对 libbpf 感兴趣的人有所帮助,帮助他们进一步开发和完善使用 libbpf 的 BPF 应用程序。
不过在继续阅读之前,建议先阅读这些文章以获取重要的背景信息:
- BPF Portability and CO-RE
- HOWTO: BCC to libbpf conversion
- Building BPF applications with libbpf-boostrap
本文假设你已经阅读了上述文章,因此这里不会有任何系统性的描述。相反,我会针对程序的某些细节部分提供对应的技巧。
程序框架(skeleton)
合并 open 和 loader 阶段
如编写的 BPF 代码不需要任何运行时调整(如调整 map 大小或设置额外配置),你可以调用 <name>__open_and_load() 将两个阶段合并,这会使我们的代码看起来更加简洁。例如:
obj = readahead_bpf__open_and_load();
if (!obj){
fprintf(stderr, "failed to open and/or load BPF objectn");
return 1;
}
err = readahead_bpf__attach(obj);
你可以在 readahead.c 中查看完整代码样例。【后续版本已经调整,原始提交参见 init readahead.c】
选择性附着 (attach)
默认情况下,<name>__attach() 会附加所有可自动 attach 的 BPF 程序。然而,有时你可能希望根据命令行参数选择性地 attach 对应的 BPF 程序。这种情况下,你可以选择主动调用 bpf_program__attach() 函数。例如:
err = biolatency_bpf__load(obj);
[...]
if (env.queued){
obj->links.block_rq_insert =
bpf_program__attach(obj->progs.block_rq_insert);
err = libbpf_get_error(obj->links.block_rq_insert);
[...]
}
obj->links.block_rq_issue =
bpf_program__attach(obj->progs.block_rq_issue);
err = libbpf_get_error(obj->links.block_rq_issue);
[...]
你可以在 biolatency.c 看到完整的代码样例。【init biolatency.c 】
自定义 load 和 attach
框架适用于几乎所

本文分享了在使用libbpf编写BPF程序时的实用技巧,包括合并open和loader阶段、选择性附着、自定义load/attach处理性能事件,以及优化map、per-CPU和全局变量的使用。
最低0.47元/天 解锁文章
5773

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



