描述:

SEC(.maps)的使用方式

在 2019 年才增加了对全局变量的支持,在此之前只能使用 eBPF map 来实现。

minimal_Legacy 可在不支持全局变量的更老旧内核上运行。全局变量 my_pid 已替换为一个仅含一个元素的数组,用于存储进程 ID(pid)。

在包含 bpf_helpers.h 头文件之前,若未定义 BPF_NO_GLOBAL_DATA 宏,则 bpf_printk 函数会使用全局变量。

代码梳理

The BPF side

SEC(“.maps”)

1
2
3
4
5
6
7
8
9
10
11
typedef unsigned int u32;
typedef int pid_t;

/* Create an array with 1 entry instead of a global variable
* which does not work with older kernels */
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, pid_t);
} my_pid_map SEC(".maps");

SEC(“tp/syscalls/sys_enter_write”)

1
2
SEC("tp/syscalls/sys_enter_write")
int handle_tp(void *ctx)

bpf_map_lookup_elem

1
2
3
4
u32 index = 0;
pid_t *my_pid = bpf_map_lookup_elem(&my_pid_map, &index);
if (!my_pid || *my_pid != pid)
return 1;

The user-space side

bpf_map__update_elem

1
2
3
4
5
6
7
8
9
10
11
pid_t pid;
unsigned index = 0;

/* ensure BPF program only handles write() syscalls from our process */
pid = getpid();
err = bpf_map__update_elem(skel->maps.my_pid_map, &index, sizeof(index), &pid,
sizeof(pid_t), BPF_ANY);
if (err < 0) {
fprintf(stderr, "Error updating map with pid: %s\n", strerror(err));
goto cleanup;
}