017. ebpf端保存数据的方式
完整来看,eBPF 的数据保存方式可以按用途模型来分,而不是按 API 名字死记。
下面我给你一套工程级分类 + 对应使用场景,基本覆盖 99% 的 eBPF 工具设计。
一、事件流(Event Stream)——“一条条往外吐”
1️⃣ Ring Buffer(推荐,现代首选)
内核 → 用户态的高性能事件通道
特点
- 单向:BPF → User
- 无需预分配 per-CPU 数组
- 支持变长数据
- lock-free(内部)
适合
- syscall / malloc / IO 事件
- tracing 日志
- 栈、结构体、字符串
**你已经在用 **👍
2️⃣ Perf Event Buffer(老方案)
Ring buffer 的前辈
特点
- 基于 perf_event
- per-CPU buffer
- API 复杂、开销更高
适合
- 老内核(< 5.8)
- perf 生态对接
📌 新项目不推荐
二、状态存储(State Store)——“在内核里记住状态”
3️⃣ Hash Map
BPF_MAP_TYPE_HASH
特点
- key → value
- 精确查找
- 用户态可读写
适合
- pid → 统计
- ptr → size(内存跟踪)
- fd → 状态
👉 eBPF 工具最常用的 map
4️⃣ LRU Hash Map
BPF_MAP_TYPE_LRU_HASH
特点
- 自动淘汰旧数据
- 防止 map 爆炸
适合
- 调用点 / 栈聚合
- 高 cardinality 数据
5️⃣ Per-CPU Hash Map
BPF_MAP_TYPE_PERCPU_HASH
特点
- 每 CPU 一份 value
- 无锁更新
适合
- 高频计数
- 延迟统计
三、计数 / 聚合(Aggregation)——“不关心每一条,只关心结果”
6️⃣ Array / Per-CPU Array
BPF_MAP_TYPE_ARRAY
BPF_MAP_TYPE_PERCPU_ARRAY
特点
- index → value
- 简单、快
适合
- 全局计数器
- histogram 桶
- 状态位
7️⃣ Histogram(本质是 Array / Per-CPU Array)
不是新 map,是用法模式
适合
- latency 分布
- size 分布
四、调用栈 / 结构化数据
8️⃣ Stack Trace Map
BPF_MAP_TYPE_STACK_TRACE
特点
- 栈去重
- 返回 stack_id
适合
- 火焰图
- 内存泄漏定位
👉 你现在课程里的核心组件之一
五、跨 CPU / 复杂结构
9️⃣ Per-CPU Maps(通用思想)
PERCPU_HASHPERCPU_ARRAY
解决的问题
- 避免锁
- 降低 cache line 抖动
六、控制 / 配置(User → BPF)
🔟 Array / Hash 作为“控制面”
用法
- 用户态写 map
- BPF 读取
适合
- 开关功能
- 设置阈值
- PID 白名单
👉 控制面 / 数据面分离
七、特殊用途 Map(高级 / 少用)
1️⃣1️⃣ Prog Array
BPF_MAP_TYPE_PROG_ARRAY
适合
- tail call
- 拆大程序
1️⃣2️⃣ LPM Trie
BPF_MAP_TYPE_LPM_TRIE
适合
- IP / prefix 匹配
- 路由类场景
1️⃣3️⃣ Queue / Stack
BPF_MAP_TYPE_QUEUE
BPF_MAP_TYPE_STACK
特点
- FIFO / LIFO
- 无 key
适合
- 简单事件缓冲
- 不推荐高频
八、快速选型表(强烈建议收藏)
| 需求 | 推荐方式 |
|---|---|
| 每次事件都要 | Ring Buffer |
| 高频计数 | Per-CPU Hash / Array |
| 查状态 | Hash / LRU Hash |
| 防爆内存 | LRU Hash |
| 栈分析 | Stack Trace Map |
| 分布统计 | Histogram(Array) |
| 用户态控制 | Hash / Array |
| 老内核 | Perf Event |
九、你可以在课里这样一句话总结(非常好)
**Ring Buffer 解决“怎么把事件送出去”,
**Map 解决“怎么在内核里记住状态”。
或者更狠一点:
**eBPF 不是数据库,
**Map 只是“必要的最小状态”

浙公网安备 33010602011771号