Skip to content

Commit 7c4eb22

Browse files
author
lipeng hao
committed
modify Makefile
1 parent cf3d736 commit 7c4eb22

11 files changed

Lines changed: 2308 additions & 1 deletion

File tree

src/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ SUBDIRS = \
2828
ssl_write \
2929
claude_trace \
3030
percpu_array \
31-
benchmark
31+
benchmark \
32+
tracee_patterns
3233

3334
# Go 语言示例 (需要单独构建,参见各自目录的 README)
3435
# GO_SUBDIRS = cilium-ebpf-go libbpfgo-helloworld

src/tracee_patterns/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
# Tracee eBPF 编程技巧示例
3+
# 展示从 Tracee 项目学到的 eBPF 最佳实践
4+
5+
APPS = tracee_patterns
6+
7+
# 额外的头文件目录
8+
EXTRA_CFLAGS = -I.
9+
10+
include ../Makefile.common

src/tracee_patterns/README.md

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Tracee eBPF 编程技巧示例
2+
3+
本示例展示了从 Aqua Security 的 [Tracee](https://github.com/aquasecurity/tracee) 项目学到的 eBPF 编程最佳实践。
4+
5+
## 目录结构
6+
7+
```
8+
tracee_patterns/
9+
├── common/ # 模块化头文件
10+
│ ├── common.h # 基础宏和工具函数
11+
│ ├── types.h # 类型定义
12+
│ ├── maps.h # BPF Map 定义
13+
│ ├── buffer.h # 缓冲区操作
14+
│ ├── core_compat.h # CO-RE 兼容性
15+
│ └── filtering.h # 位图过滤器
16+
├── tracee_patterns.bpf.c # BPF 程序
17+
├── tracee_patterns.c # 用户空间程序
18+
├── Makefile
19+
└── README.md
20+
```
21+
22+
## 核心技巧
23+
24+
### 1. 模块化代码组织
25+
26+
将代码按功能拆分到不同头文件,提高可维护性:
27+
28+
```c
29+
#include "common/common.h" // 基础宏
30+
#include "common/types.h" // 类型定义
31+
#include "common/maps.h" // Map 定义
32+
#include "common/buffer.h" // 缓冲区操作
33+
```
34+
35+
### 2. statfunc 强制内联
36+
37+
eBPF 不支持真正的函数调用,使用 `__always_inline` 确保内联:
38+
39+
```c
40+
#define statfunc static __always_inline
41+
42+
statfunc int my_helper_function(void *arg) {
43+
// ...
44+
}
45+
```
46+
47+
### 3. 分支预测优化
48+
49+
使用 `likely/unlikely` 优化热路径:
50+
51+
```c
52+
if (unlikely(ptr == NULL))
53+
return 0;
54+
55+
if (likely(condition))
56+
do_common_case();
57+
```
58+
59+
### 4. 内联汇编边界检查
60+
61+
满足 verifier 对变量边界的要求:
62+
63+
```c
64+
// 确保 size 不超过 MAX_SIZE
65+
asm volatile("if %[size] < %[max] goto +1;\n"
66+
"%[size] = %[max];\n"
67+
:
68+
: [size] "r"(size), [max] "i"(MAX_SIZE));
69+
```
70+
71+
### 5. CO-RE 跨内核兼容
72+
73+
使用 `bpf_core_*` 函数处理内核版本差异:
74+
75+
```c
76+
// 检查字段是否存在
77+
if (bpf_core_field_exists(task->start_boottime))
78+
return BPF_CORE_READ(task, start_boottime);
79+
80+
// 检查函数是否可用
81+
if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_ktime_get_boot_ns))
82+
return bpf_ktime_get_boot_ns();
83+
```
84+
85+
### 6. Tail Call 链式调用
86+
87+
突破 BPF 指令数量限制:
88+
89+
```c
90+
SEC("raw_tracepoint/sys_enter")
91+
int tracepoint_sys_enter(struct bpf_raw_tracepoint_args *ctx)
92+
{
93+
// 使用 tail call 跳转到下一个程序
94+
bpf_tail_call(ctx, &prog_array, TAIL_SYSCALL_ENTER_INIT);
95+
return 0;
96+
}
97+
```
98+
99+
### 7. PerCPU Buffer 规避栈限制
100+
101+
eBPF 栈限制 512 字节,使用 PerCPU Array 存储大型数据:
102+
103+
```c
104+
struct {
105+
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
106+
__uint(max_entries, 1);
107+
__type(key, u32);
108+
__type(value, event_data_t); // 可能很大
109+
} event_data_map SEC(".maps");
110+
```
111+
112+
### 8. 位图策略过滤
113+
114+
使用 64 位整数同时评估 64 个策略:
115+
116+
```c
117+
// equals_in_policies: 哪些策略匹配
118+
// key_used_in_policies: 哪些策略使用了这个 key
119+
// 返回匹配的策略位图
120+
return equals_in_policies | (match_if_key_missing & ~key_used_in_policies);
121+
```
122+
123+
### 9. X 宏生成枚举
124+
125+
避免重复定义:
126+
127+
```c
128+
#define EVENT_LIST \
129+
X(EVENT_NONE, = 0) \
130+
X(EVENT_PROCESS_EXEC, ) \
131+
X(EVENT_PROCESS_EXIT, )
132+
133+
typedef enum {
134+
#define X(name, val) name val,
135+
EVENT_LIST
136+
#undef X
137+
} event_id_t;
138+
```
139+
140+
### 10. 限流日志
141+
142+
避免相同日志大量输出:
143+
144+
```c
145+
// 使用 map 记录日志计数和时间戳
146+
// 2 秒内相同日志不重复输出
147+
if ((now - last_ts) < 2000000000ULL) {
148+
count++;
149+
return; // 不输出
150+
}
151+
```
152+
153+
## 编译和运行
154+
155+
```bash
156+
# 编译
157+
make
158+
159+
# 运行 (需要 root 权限)
160+
sudo ./tracee_patterns
161+
```
162+
163+
## 输出示例
164+
165+
```
166+
=== Tracee eBPF Patterns Demo ===
167+
展示从 Tracee 学到的 eBPF 编程技巧
168+
169+
TIME EVENT CPU PID TID UID COMM DETAILS
170+
─────────────────────────────────────────────────────────────────────────────────
171+
14:30:15.123456 PROCESS_EXEC 0 12345 12345 1000 bash FILE:/usr/bin/ls
172+
14:30:15.123789 FILE_OPEN 0 12345 12345 1000 ls DFD:-100 FILE:/etc/passwd
173+
14:30:15.124001 PROCESS_EXIT 0 12345 12345 1000 ls EXIT_CODE:0
174+
```
175+
176+
## 参考
177+
178+
- [Tracee GitHub](https://github.com/aquasecurity/tracee)
179+
- [Tracee eBPF 源码](https://github.com/aquasecurity/tracee/tree/main/pkg/ebpf/c)
180+
- [BPF CO-RE 参考指南](https://nakryiko.com/posts/bpf-core-reference-guide/)

0 commit comments

Comments
 (0)