ebpf:关闭 bpf 对象并链接实例

ebpf: close bpf object and links instances

所以,我正在研究 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 对象实例吗,例如bpf_object__close(obj) 或者 objlinks 必须存在并且只要程序加载到内核中就可以访问?

我没有 运行 具体测试来回答你的问题,但根据我的理解:“这取决于”,特别是程序类型。您可能会关闭 obj,但如果您也关闭 links,那么当您的用户 space 加载程序终止时,跟踪 eBPF 程序可能会被分离和卸载。

eBPF 程序生命周期

一旦加载,eBPF 程序就会保留在内核中,只要它的引用计数器严格保持为正数。有许多“句柄”可以保存对程序的引用:

  • 将程序附加到挂钩(例如 TC 过滤器或内核探测)会增加计数器。
  • 加载程序时或向已加载程序请求文件描述符时从内核返回的文件描述符也包含一个引用。
  • eBPF 虚拟文件系统中的固定路径做同样的事情。
  • BPF_MAP_TYPE_PROG_ARRAY 映射中引用一个程序(对于尾调用)也包含一个引用。

当所有这些句柄都消失时 - 当程序被分离时,加载它的用户应用程序终止,并且它没有固定到 bpffs,然后程序被卸载。

eBPF 链接

所以我们说附加程序会增加其引用计数器,这意味着只要程序被附加,它就会保持加载状态。例如,对于 TC 过滤器或 XDP 程序,这使事情变得更容易,因为用户应用程序可以附加程序并安全终止 - 程序保持附加和加载。对于跟踪,附加探测器通常通过调用 perf_event_open()、检索文件描述符(不同于我们在加载 eBPF 程序时获得的描述符)并使用它附加 ioctl() 来完成。当这个文件描述符 关闭,程序脱离【注意:这是我对附加探针的基本理解,也许我漏掉了什么,也许还有其他解决方案】。因此,当用户应用程序终止时,两个文件描述符(来自加载和附加)都会关闭,并且程序会同时分离和卸载。固定程序可防止卸载,但不能分离(因此程序已加载到内核中但从未 运行)。

作为解决方法,引入了 eBPF links 来为附加​​程序提供更好的用户体验,使其更容易保持附加,并更一致地管理 attachment/detachment。 struct bpf_link 引用附加程序时获得的文件描述符。 link 可以固定以在用户应用程序终止时保持持久性,从而确保探测保持活动状态。

objlinks

在你的情况下,如果你关闭 objlinks 会发生什么?

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,我们也失去了固定 link 的可能性。该进程仍然持有来自 perf_event_open() 的文件描述符,但它会在退出时将其关闭。如果 eBPF 程序是一个跟踪程序,它将立即被分离和卸载。如果它是一个网络程序,它应该保持附加。

所以这完全取决于您的程序类型以及您是否希望您的程序保持 运行ning。对于跟踪和监控用例,固定的 eBPF links 允许您即使在用户 space 加载程序退出时也能继续探测。因此,在删除它们之前,可能值得仔细检查您不再需要那些 links :).