在我的理解中,当用户空间使用bpf_map_update_elem(int fd, void *key, void *value, __u64 flags)
时,
首先,用户空间通过fd
找到地图;
第二,用户空间在用户空间中形成内存;
和。。。。
我知道一点,但具体过程还不清楚。
所以我想知道用户空间运行 API 映射助手时的细节是什么。
因为你提到了"用户空间",我不确定你在说什么。因此,让我们从一些澄清开始。
BPF 映射(或至少大多数现有类型,包括哈希映射和数组(可以通过两种方式访问:
- 从用户空间,由系统上运行并具有足够权限的任何应用程序
- 从内核空间,从 BPF 程序
从用户空间来看,没有"助手"功能。与映射的交互完全(*(通过bpf()
系统调用完成(BPF_MAP_LOOKUP_ELEM
、BPF_MAP_UPDATE_ELEM
、BPF_MAP_DELETE_ELEM
命令作为其第一个参数传递给系统调用(。有关更多详细信息,请参阅bpf(2)
手册页。这是您在用户空间应用程序中使用的内容,该应用程序将加载和管理 BPF 程序和映射,例如bpftool
。
从内核空间,即从 BPF 程序,事情的工作方式不同,访问是通过 BPF "助手"之一(如bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
(完成的。有关现有帮助程序的详细信息,请参见bpf-helpers(7)
手册页。您可以在 Cilium 指南中找到有关这些帮助程序调用的详细信息,或者显然可以通过阅读内核代码(例如数组映射(找到。它们看起来像低级 C 函数调用,使用 BPF 寄存器传递必要的参数,然后它从 BPF 程序指令调用到作为内核二进制文件的一部分编译的帮助程序中。
所以你提到了bpf_map_update_elem()
和用户空间。虽然这是内核端帮助程序的名称,但我怀疑您可能在谈论 libbpf 库提供的同名函数,以提供围绕bpf()
系统调用的包装器。因此,此函数发生的情况非常简单。
- 中查找映射:实际上情况恰恰相反,文件描述符是从用户空间中的映射打开的(例如,从其映射 ID 或从/sys/fs/bpf 虚拟文件系统下的固定路径(。因此,fd 被传递给
bpf()
系统调用,并由内核用作对映射的引用。 - 我不确定你的意思,但"用户空间在用户空间中产生内存"。这里不需要分配任何内存:此时
key
和value
应该已经填满,它们通过bpf()
系统调用传递给内核,以告知要更新的条目以及值。旗帜也是如此。 - 一旦调用了
bpf()
,内核端发生的事情就相当简单了。大多数情况下,内核检查权限,验证参数(以确保它们安全且与映射一致(,然后更新实际数据。对于数组映射,最终会调用array_map_update_elem()
(也与内核端的 BPF 帮助程序一起使用,请参阅上面的链接(。
(*( 某些交互实际上可以在没有bpf()
系统调用的情况下完成,我相信使用存储在 BPF 映射中的"全局数据",使用内核内存mmap()
的应用程序。但这超出了数组和映射的基本用法范围。