c - 一个元素的 eBPF 映射。映射类型和内核/用户空间通信
问题描述
我会创建一个映射来仅存储一个元素(端口号),并且应该从用户空间和内核空间读取/写入它。我应该使用哪种地图类型?哪个大小的键和值是合适的,我如何从双方写入/读取?
_user.c
/* create array map with one element */
map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value), 1, 0);
...
/* update map */
ret = bpf_map_update_elem(map_fd, &key, &i, BPF_ANY);
_kern.c
如何引用 map_fd 并在同一张地图上操作?
编辑:
我只能通过一种方式成功地创建地图并与之交互:在_kern.c
文件中定义地图,如下所示:
struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(uint32_t),
.value_size = sizeof(uint32_t),
.max_entries = 1,
};
该定义允许使用 bpf 助手直接在地图上进行操作,例如bpf_map_lookup_elem
.
而是在通过我使用将ebpf 程序_user.c
加载到内核之后_kern.o
bpf_prog_load
map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
检索与地图关联的文件描述符(我错过了这一点)。例如,一旦您获得要执行的文件描述符,您就可以调用地图更新
ret = bpf_map_update_elem(map_fd, &key, &value, BPF_ANY);
问题:在这种情况下,我使用 libbpf 从用户空间检索 fd,但是如果我从中创建映射_user.c
,bpf_create_map
那么如何从 ebpf 程序中检索 fd?
解决方案
如果你知道你只有一个元素,最简单的可能是使用数组映射。在这种情况下,您可以通过数组中的索引轻松访问您的地图条目:0
。
如果你这样做,键的大小将是一个 4 字节整数 ( sizeof(uint32_t)
) 的大小,它总是用于数组索引。该值的大小将是您存储端口号所需的大小:很可能是sizeof(uint16_t)
.
然后,您可以通过调用相关的 BPF 辅助函数从您的 BPF 程序中读取/写入:bpf_map_lookup_elem()
或bpf_map_update_elem()
(有关详细信息,请参见手册页)。它们通常被定义在bpf_helpers.h
您的系统上通常不安装的位置,您可以在 bcc 或内核 repo 中找到它的版本。
在用户空间中,您可以使用bpf()
系统调用及其相关命令来更新条目:BPF_MAP_LOOKUP_ELEM()
和BPF_MAP_UPDATE_ELEM()
(参见手册页)。但是您不一定必须自己重新实现调用:如果您编写程序,您可能应该看看提供包装器的 libbpf。如果你想从命令行更新你的地图,这很容易做到bpftool
(见手册页),比如bpftool map <map_ref> update key 0 0 0 0 value 0x37 0x13
(更新)或bpftool map <map_ref> lookup key 0 0 0 0
(查找)。
推荐阅读
- graphql - GitHub GraphQL 查询 - 按用户统计给定月份的 PR 评论
- r - 替换R中数据框中的多个值
- vba - Excel vba 检查 Match 函数是否返回 NA - 宏崩溃:运行时错误 1004“应用程序定义或对象定义错误”
- javascript - Next.JS:无法在 getInitialProps 中调用内部 API。出现错误:读取 ECONNRESET
- angular - 自定义验证 - if 语句
- tvos - 是否可以通过无线方式将企业/内部 tvOS 应用程序分发到 Apple TV?
- .net - 如何在 Azure AD B2C 登录的 webview 屏幕中删除 URL
- tabs - 如何将 konsole 选项卡放在左侧?
- ssl - 在非阻塞模式下,openssl 允许在客户端使用任何证书
- reactjs - Jest,Enzyme,React - 测试 Iframe OnLoad