Linux kernel BPF:地图的所有者

Linux kernel BPF:地图的所有者,linux-kernel,bpf,Linux Kernel,Bpf,这是我的后续问题,因为我的新问题与该线程没有直接关系 所以,在我看来,创建BPF映射的地方必须只有一个点,要么是BPF程序,要么是加载BPF的用户程序,等等 BPF程序必须知道编译时要使用的映射类型,因此我们需要: struct bpf_map_def SEC("maps") my_map = { ... }; 因此,这意味着一个用户程序,例如bpftool,将启动在bpf ELF部分中找到的映射的创建,如线程中所示 另一方面,用户应用程序需要在地图中添加/删除条目。要实现这一点,它必须知道m

这是我的后续问题,因为我的新问题与该线程没有直接关系

所以,在我看来,创建BPF映射的地方必须只有一个点,要么是BPF程序,要么是加载BPF的用户程序,等等

BPF程序必须知道编译时要使用的映射类型,因此我们需要:

struct bpf_map_def SEC("maps") my_map = {
...
};
因此,这意味着一个用户程序,例如
bpftool
,将启动在bpf ELF部分中找到的映射的创建,如线程中所示

另一方面,用户应用程序需要在地图中添加/删除条目。要实现这一点,它必须知道map的
ID
,以便使用
bpf\u map\u get\u fd\u by\u ID()
libbpf
获取map的fd。之后,我们可以享受
bpf\u map\u update\u elem()
和类似的API

另一方面,如果我们在BPF程序中声明了一个映射节,并且使用了映射API,那么映射将保留在内核中,并将被分配ID

因此,在本例中,我们将有两个具有两个不同ID的映射:一个是由
bpftool
中的
bpf\u prog\u load()
创建的,另一个是由用户应用程序的
bpf\u create\u map()
创建的(假设应用程序继续运行,例如更新映射,并且不返回shell)


一定有办法绕过这个模棱两可的问题吗?

我不能完全确定我是否理解你的问题,让我试着重新表述一下

  • 使用
    bpftool
    加载eBPF程序,该程序将创建程序所需的所有贴图
    bpftool
    是一个用户空间应用程序,最终使用
    bpf(bpf\u MAP\u CREATE,…)
    syscall创建地图
  • 您还有另一个用户空间应用程序
    foobar
    ,它可以与这些映射进行交互,可能是通过使用libbpf(最终执行
    bpf(bpf_-MAP_*,…)
    syscalls)来查找、更新或删除映射中的元素
  • 据我所知,第二个应用程序
    foobar
    也尝试创建地图。因此,由
    bpftool
    创建的映射与由
    foobar
    创建的映射之间存在冲突
如果这是正确的,那么解决方案是“简单的”:不要创建两次贴图

这意味着您应该从其他应用程序
foobar
中删除对
bpf\u create\u map()
的调用,或者用
bpftool
以外的东西加载程序。通常,工作流包含eBPF对象文件中描述的映射,并由加载程序的同一应用程序创建,加载前这就是
bpftool
所做的。然后,应用程序拥有映射的文件描述符并可以处理它

或者,可以将映射固定在BPF虚拟文件系统(
/sys/fs/BPF/
)下,以便其他应用程序可以检索文件描述符,也可以访问此映射。这是通过系统调用bpf(bpf_OBJ_GET,…)完成的(至少在我的系统上,目前还没有在手册页上记录)

如果我是正确的,那么在加载新的eBPF程序时,使用固定贴图也可以允许重用已经存在的贴图。我相信,如果所描述的映射存在并且已经被钉住(请参见文件
lib/bpf.c
,但代码并不容易阅读),那么来自包iproute2的
tc
打算这样做。这通常在重新定位时执行

最近添加了映射id,主要用于调试或内省,但在您的情况下,它们可能会提供另一种将文件描述符检索到映射的方法,如您在
bpf\u map\u get\u fd\u by\u id()中所述。虽然你必须首先找到一种方法来获取ID

希望这有帮助