我没有运行具体的测试来回答您的问题,但根据我的理解:“这取决于”,特别是取决于程序类型。你可以关闭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 和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 :)。