linux-kernel - ebpf:关闭 bpf 对象并链接实例
问题描述
因此,我正在研究samples/bpf/*
示例,并在最近使用的代码中发现了以下模式libbpf
:
struct bpf_link *links[PROGS_NUM] = { NULL, };
struct bpf_program *prog;
struct bpf_object *obj;
int i = 0;
obj = bpf_object__open_file(filename, NULL);
bpf_object__load(obj);
bpf_object__for_each_program(prog, obj) {
links[i] = bpf_program__attach(prog);
i++;
}
现在,在附加程序之后,是否可以关闭bpf
对象实例,例如,只要程序加载到内核中,and 就必须存在并且可以bpf_object__close(obj)
访问obj
?links
解决方案
我没有运行具体的测试来回答你的问题,但根据我的理解:“这取决于”,特别是取决于程序类型。您可能会关闭obj
,但如果您也关闭links
,那么当您的用户空间加载程序终止时,跟踪 eBPF 程序可能会被分离和卸载。
eBPF 程序生命周期
一旦加载,只要它的引用计数器保持严格的正数,eBPF 程序就会保留在内核中。有许多“句柄”可以保存对程序的引用:
- 将程序附加到钩子(例如 TC 过滤器或内核探针)会增加计数器。
- 在加载程序或向加载的程序请求文件描述符时从内核返回的文件描述符也包含一个引用。
- eBPF 虚拟文件系统中的固定路径做同样的事情。
- 在地图中引用程序
BPF_MAP_TYPE_PROG_ARRAY
(用于尾调用)也包含引用。
当所有这些句柄都消失时 - 当程序被分离时,加载它的用户应用程序终止,并且它没有固定到 bpffs,然后程序被卸载。
eBPF 链接
所以我们说附加一个程序会增加它的引用计数器,这意味着只要附加了程序,它就会保持加载状态。例如,对于 TC 过滤器或 XDP 程序,这使事情变得更容易,因为用户应用程序可以附加程序并安全终止 - 程序保持附加和加载。对于跟踪,附加一个探针通常是通过调用perf_event_open()
,检索一个文件描述符(与我们在加载 eBPF 程序时得到的不同),然后使用它来附加一个ioctl()
. 当这个文件描述符被关闭时,程序被分离[注:这是我对附加探针的基本理解,可能我遗漏了一些东西,可能还有其他解决方案]。因此,当用户应用程序终止时,两个文件描述符(来自加载和附加)都被关闭,并且程序同时被分离和卸载。固定程序可以防止卸载,但不会分离(因此程序被加载到内核中但从不运行)。
作为一种变通方法,引入了 eBPF 链接来为附加程序提供更好的用户体验,使其更容易保持附加,并且更一致地管理附件/分离。引用附加程序时获得的struct bpf_link
文件描述符。当用户应用程序终止时,可以固定链接以保持持久性,从而确保探测器保持活动状态。
obj
和links
在您的情况下,如果您关闭obj
and会发生什么links
?
obj
是一个(指向 a 的指针)struct bpf_object
,其内部被 libbpf 对用户隐藏。它是从一个目标文件构建的,并在加载包含在该目标文件中的 eBPF 程序时进行更新。它包含指向struct bpf_program
对象的指针instances
,最后fds
是加载程序时获得的文件描述符。如果我们关闭它们(通过bpf_object__close()
,调用bpf_object__unload()``, and in turn
bpf_program__unload() ), those handles for keeping the program are gone. This is not an issue, as long as other references are kept elsewhere - for example, if the program is attached. So I _think_ that
obj` 应该可以安全关闭。
如果我们也关闭links
了,我们也失去了固定链接的可能性。该进程仍然持有来自 的文件描述符perf_event_open()
,但它会在退出时将其关闭。如果 eBPF 程序是一个跟踪程序,它将立即被分离和卸载。如果它是一个网络程序,它应该保持连接。
因此,这完全取决于您的程序类型以及您是否希望程序继续运行。对于跟踪和监控用例,固定的 eBPF 链接允许您在用户空间加载器应用程序退出时继续探测。因此,在删除它们之前,可能值得仔细检查您是否不再需要links
它们:)。
推荐阅读
- angular - 在 Angular 中的 TextArea 内的当前(或最后一个)插入符号位置插入文本;元素不被解释为 TextArea
- docker - 为什么相同的 Docker 映像会在不同的存储库上生成具有不同 SHA-256 的不同清单?
- c# - 由于游戏对象处于非活动状态,无法启动 Couroutine
- c++ - 何时在 GCC 的成员函数指针中使用 delta?
- indexing - 为什么在 EF Core 中默认只为复合 PK 定义一个索引?
- python - 如何根据深度嵌套的键对嵌套字典列表进行排序?
- c# - 使用 EF 框架的 .NET 核心 MVC - 将数据从一个控制器传递到另一个控制器
- docker - 如何将多个参数传递给容器
- database - 如何对标称属性进行一次热编码以输出为完整的二进制文件?
- jmeter - 处理 JTL 日志阶段失败并出现错误“groovy.lang.MissingPropertyException: No such property: jtl for class: java.lang.String”