首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >谁在BPF中创建地图?

谁在BPF中创建地图?
EN

Stack Overflow用户
提问于 2018-01-02 20:05:14
回答 2查看 2.4K关注 0票数 11

在阅读了man bpf和其他一些文档之后,我的印象是map只能由用户进程创建。然而,下面的小程序似乎神奇地创建了bpf映射:

代码语言:javascript
复制
struct bpf_map_def SEC("maps") my_map = {
        .type = BPF_MAP_TYPE_ARRAY,
        .key_size = sizeof(u32),
        .value_size = sizeof(long),
        .max_entries = 10,
};

SEC("sockops")
int my_prog(struct bpf_sock_ops *skops)
{
   u32 key = 1;
   long *value;
   ...

   value = bpf_map_lookup_elem(&my_map, &key);
   ...
   return 1;
}

因此,我使用内核的tools/bpf/bpftool加载程序,并验证程序是否已加载:

代码语言:javascript
复制
$ bpftool prog show
1: sock_ops  name my_prog  tag f3a3583cdd82ae8d
        loaded_at Jan 02/18:46  uid 0
        xlated 728B  not jited  memlock 4096B

$ bpftool map show
1: array  name my_map  flags 0x0
        key 4B  value 8B  max_entries 10  memlock 4096B

当然地图是空的。但是,从程序中删除bpf_map_lookup_elem会导致没有创建任何映射。

UPDATE I用strace调试了它,发现在这两种情况下,即使用bpf_map_lookup_elem和没有bpf_map_lookup_elem,bpftool确实调用了bpf(BPF_MAP_CREATE, ...),并且显然成功了。然后,在bpf_map_lookup_elem遗漏的情况下,我使用bpftool map showbpf(BPF_MAP_GET_NEXT_ID, ..)立即返回ENOENT,它永远无法转储地图。所以很明显,有些东西并没有完成地图的创建。

所以我想知道这是否是预期的行为?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-03 10:03:43

正如antiduh所解释的,并通过您的strace检查确认了,bpftool是在本例中创建映射的用户空间程序。它从libbpf (在tools/lib/bpf/下)调用函数bpf_prog_load(),然后执行syscall。然后将程序固定在所需的位置(在bpf虚拟文件系统挂载点下),以便在bpftool返回时不会卸载它。地图没有固定。

关于地图创建,魔法比特也发生在libbpf中。当调用bpf_prog_load()时,libbpf接收对象文件的名称作为参数。bpftool不要求加载这个特定的程序或那个特定的映射;相反,它提供了对象文件,libbpf必须处理它。因此libbpf中的函数解析这个ELF对象文件,并最终找到一些对应于映射和程序的部分。然后尝试加载第一个程序。

加载此程序包括以下步骤:

代码语言:javascript
复制
CHECK_ERR(bpf_object__create_maps(obj), err, out);
CHECK_ERR(bpf_object__relocate(obj), err, out);
CHECK_ERR(bpf_object__load_progs(obj), err, out);

换句话说:从创建在对象文件中找到的所有映射开始。然后执行映射重定位(即将映射索引与eBPF指令相关联),最后加载程序指令。

因此,关于您的问题:在这两种情况下,无论是否使用bpf_map_lookup_elem(),映射都是用bpf(BPF_MAP_CREATE, ...) syscall创建的。在此之后,重新定位就会发生,如果需要的话,程序指令将被调整为指向新创建的映射。然后,一旦完成所有步骤并加载程序,bpftool就会退出。eBPF程序应该是固定的,并且仍然加载在内核中。据我所知,如果它确实使用了映射(如果使用了bpf_map_lookup_elem() ),那么映射仍然被加载的程序引用,并保存在内核中。另一方面,如果程序不使用映射,那么就没有什么可以阻止它们的了,所以当bpftool持有的文件描述符关闭时,当bpftool返回时,映射就会被销毁。

因此,最后,当bpftool完成时,如果程序使用它,就会在内核中加载一个映射,但是如果没有程序依赖它,则没有映射。在我看来,这听起来像是一种预期的行为;但是,如果您在bpftool中遇到了奇怪的事情,那么请以这样或那样的方式执行ping操作,我就是这个实用程序的工作人员之一。最后一个一般性的观察是:地图也可以固定在内核中,即使没有程序使用它们,如果需要保持它们在一起的话。

票数 12
EN

Stack Overflow用户

发布于 2018-01-02 20:52:10

我当时的印象是,地图只能由用户进程创建。

您完全正确--用户程序是调用bpf系统调用以加载eBPF程序和创建eBPF映射的程序。

你就是这么做的:

所以我用工具/bpf/bpftool加载程序.

bpftool程序是调用bpf syscall的用户进程,因此是创建eBPF映射的用户进程。

当创建BPF程序的用户程序可能使用此机制时,就不必卸载BPF程序。

一些相关的位从手册页连接点:

用户进程可以创建多个映射..。并通过文件描述符访问它们。 通常,eBPF程序由用户进程加载,并在进程退出时自动卸载。在某些情况下..。即使在加载程序的进程退出之后,程序仍将在内核中保持活跃。 每个eBPF程序都是一组安全运行直到完成的指令。..。在验证过程中,内核会增加eBPF程序使用的每个映射的引用计数,以便在卸载程序之前不能删除附加的映射。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48067163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档