这是who creates map in BPF的后续行动,因为我的新问题与该主题没有直接关系。
所以,在我看来,必须有一个 point ,其中创建了BPF地图,无论是bpf程序还是加载bpf等的用户程序。
BPF程序必须知道它将在编译时使用的地图类型,因此我们需要:
struct bpf_map_def SEC("maps") my_map = {
...
};
因此,这意味着用户程序(例如bpftool
)将启动在bpf ELF部分中找到的映射的创建,如who creates map in BPF线程中所示。
另一方面,用户应用程序需要在地图中添加/删除条目。要做到这一点,必须知道地图的ID
,以便从bpf_map_get_fd_by_id()
获取libbpf
获取地图的fd。之后,我们可以享受bpf_map_update_elem()
和类似的API。
另一方面,如果我们在BPF程序中声明了一个map部分并且确实使用了map API,那么地图将保留在内核中并将被分配ID。
因此,在这种情况下,我们将有两个具有两个不同ID的地图:一个是bpf_prog_load()
从bpftool
创建的,另一个是来自用户应用程序的bpf_create_map()
(假设应用程序继续运行,例如更新映射,并且不返回shell)。
必须有办法绕过这种歧义吗?
答案 0 :(得分:3)
我不完全确定我理解你的问题,让我试着改写一下。
bpftool
加载eBPF程序,该程序会创建程序所需的所有地图。 bpftool
是用户空间应用程序,最终使用bpf(BPF_MAP_CREATE, …)
系统调用创建地图。foobar
,可能通过使用libbpf(最终执行bpf(BPF_MAP_*, …)
系统调用)来查找,更新或删除地图中的元素。 foobar
也尝试创建地图。因此,bpftool
创建的地图与foobar
创建的地图之间存在冲突。如果这是正确的,解决方案是“简单的”:不创建地图两次。
这意味着您应该从其他应用bpf_create_map()
中删除对foobar
的来电,或者使用bpftool
之外的其他内容加载您的程序。通常,工作流程包括在eBPF目标文件中描述的映射,并且由加载程序的同一应用程序创建,就在加载之前 - 这是bpftool
的作用。然后,应用程序具有地图的文件描述符,可以使用它。
或者,可以将地图固定在BPF虚拟文件系统(/sys/fs/bpf/
)下,以便其他应用程序可以检索文件描述符,并访问此映射。这是通过系统调用bpf(BPF_OBJ_GET, …)
完成的(目前尚未在手册页上记录,至少在我的系统上)。
如果我是正确的,使用固定地图还可以允许人们在加载新的eBPF程序时重用已经存在的地图。我相信来自包iproute2的tc
打算如果所描述的地图存在并且已经固定(参见文件lib/bpf.c
,但是代码不是很容易阅读)。这通常会在重定位时执行。
最近添加了地图ID,主要用于调试或内省,但它们可能提供另一种方法来检索文件描述符到您的案例中的地图,正如您使用bpf_map_get_fd_by_id()
所描述的那样。虽然您必须首先找到获取ID的方法。
希望这有帮助!