eBPF多map遍历问题:如何迭代访问多个已pinned的BPF哈希map
可行实现方案
你定义的3个pinned map的key、value类型完全一致,有两种成熟的实现方案,按需选择即可:
方案1:内核态遍历(使用BPF_ARRAY_OF_MAPS)
这是map of maps的正确用法,分三步实现:
- 内核态eBPF代码中定义array of maps
// 定义容量为3的数组映射,每个元素指向同类型的hash map,key/value类型和你的子map保持一致 BPF_ARRAY_OF_MAPS(map_array, struct mapkey, struct output_f, 3);
- 用户空间初始化赋值
加载eBPF程序后,把3个pinned map的fd写入array of maps的对应位置:
// 获取pinned map的fd int map1_fd = bpf_obj_get("/sys/fs/bpf/map1"); int map2_fd = bpf_obj_get("/sys/fs/bpf/map2"); int map3_fd = bpf_obj_get("/sys/fs/bpf/map3"); // 写入array of maps int idx = 0; bpf_map_update_elem(bpf_map__fd(skel->maps.map_array), &idx, &map1_fd, BPF_ANY); idx = 1; bpf_map_update_elem(bpf_map__fd(skel->maps.map_array), &idx, &map2_fd, BPF_ANY); idx = 2; bpf_map_update_elem(bpf_map__fd(skel->maps.map_array), &idx, &map3_fd, BPF_ANY);
- 内核态遍历逻辑
在内核态eBPF代码中直接循环遍历即可,注意固定次数循环需要展开以通过eBPF校验:
#pragma unroll // 必须加,让编译器展开3次循环 for (int i = 0; i < 3; i++) { // 获取当前遍历的hash map引用 void *cur_map = bpf_map_lookup_elem(&map_array, &i); if (!cur_map) continue; // 遍历当前hash map的所有元素 struct mapkey *key = NULL; struct output_f val; while (bpf_map_get_next_key(cur_map, key, &key) == 0) { if (bpf_map_lookup_elem(cur_map, key, &val) == 0) { // 此处填写你的业务处理逻辑 } } }
方案2:用户态直接遍历
如果遍历逻辑不需要放在内核态,用户态实现更简单,不需要修改内核eBPF代码:
const char *map_paths[] = {"/sys/fs/bpf/map1", "/sys/fs/bpf/map2", "/sys/fs/bpf/map3"}; for (int i = 0; i < 3; i++) { int fd = bpf_obj_get(map_paths[i]); if (fd < 0) continue; struct mapkey *key = NULL; struct output_f val; // 遍历当前map的所有元素 while (bpf_map_get_next_key(fd, key, &key) == 0) { if (bpf_map_lookup_elem(fd, key, &val) == 0) { // 此处填写你的业务处理逻辑 } } close(fd); }
原方法失败原因说明
你之前尝试构造void指针数组不可行,是因为eBPF编译工具链会为每个map生成独立的专属类型,不符合eBPF校验器的类型安全要求,无法通过编译和加载校验。
内容的提问来源于stack exchange,提问作者veryconfusedrobot
相关产品推荐
相关产品推荐

