据我了解,当用户空间使用 bpf_map_update_elem(int fd, void *key, void *value, __u64 flags)
,
首先,用户空间通过fd
找到 map ;
第二,用户空间在用户空间创建一个内存;
还有......
知道一点,但具体流程还不清楚。
所以我想知道用户空间运行 API map 助手时的详细信息。
最佳答案
因为你提到“用户空间”,我不确定你到底在说什么。因此,让我们首先进行一些澄清。
BPF 映射(或者至少大多数现有类型,包括 HashMap 和数组)可以通过两种方式访问:
- 来自用户空间,由系统上运行且具有足够权限的任何应用程序实现
- 来自内核空间,来自 BPF 程序
从用户空间来看,没有“帮助程序”功能。与 map 的交互完全 (*) 通过 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 guide 中找到有关这些帮助程序调用的详细信息。 ,或者显然通过阅读内核代码(例如 for array maps )。它们看起来像低级 C 函数调用,使用 BPF 寄存器传递必要的参数,然后从 BPF 程序指令调用到编译为内核二进制文件一部分的帮助程序。
所以你提到了bpf_map_update_elem()
和用户空间。虽然这是内核端帮助程序的名称,但我怀疑您可能正在谈论 libbpf 库提供的同名函数,以提供 wrapper around the bpf()
system call 。所以这个函数发生的事情相当简单。
- 不需要从用户空间的文件描述符中查找映射:实际上相反的情况发生,文件描述符是从用户空间的映射中打开的(从其映射ID,或从其/sys下的固定路径)例如/fs/bpf 虚拟文件系统)。所以fd被传递到
bpf()
系统调用并被内核用作对映射的引用。 - 我不确定你的意思,但“用户空间在用户空间中创建内存”。这里不需要分配任何内存:
key
和value
此时应该已经被填充,并且它们通过bpf()
传递到内核。系统调用来告诉要更新哪些条目以及更新什么值。旗帜也是如此。 - 一次
bpf()
已经被调用了,内核端发生的事情相当简单。主要是内核 check permissions ,验证参数(以确保它们安全且与 map 一致),然后更新实际数据。对于数组映射,array_map_update_elem()
(也与内核端的 BPF 帮助器一起使用,请参阅上面的链接)最终被调用。
(*) 某些交互实际上可能在没有 bpf()
的情况下完成系统调用,我相信通过存储在 BPF 映射中的“全局数据”,使用应用程序 mmap()
到内核内存。但这超出了数组和映射的基本使用范围。
关于c - 像 "bpf_map_update_elem"这样的bps API map 助手的详细过程是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59782101/