You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在BCC结构体中用数组存储系统调用列表的实现疑问

BCC eBPF 存储进程系统调用数组的实现方案

完全可以实现为每个进程存储系统调用数组的需求,你遇到的memset不支持错误,是因为eBPF虚拟机对标准C库函数有严格限制,同时代码中还存在变量访问顺序、语法补全的问题,以下是正确的实现方式:

关键修正点

  • 避免使用标准C库的memset,改用结构体初始化器完成零值初始化
  • 调整原子递增操作的顺序,确保数组索引正确
  • 添加数组边界检查,防止越界访问
  • 补全代码语法细节(如结构体分号、探针函数括号)

完整代码片段

#define MAX_SYSCALLS 1024  // 根据需求定义数组最大长度

struct data_t {
    u32 syscalls[MAX_SYSCALLS];
    u64 count;
};

// 定义哈希表,键为PID-TGID,值为进程的系统调用记录
BPF_HASH(data_map, u32, struct data_t);

TRACEPOINT_PROBE(raw_syscalls, sys_exit) {
    // 获取当前进程的PID-TGID作为key
    u32 key = bpf_get_current_pid_tgid();
    struct data_t *val, zero = {0};

    // 查找或初始化进程对应的记录
    val = bpf_map_lookup_or_try_init(&data_map, &key, &zero);
    if (!val) {
        return 0;
    }

    // 原子获取当前count值并递增,确保索引正确
    u64 idx = __sync_fetch_and_add(&val->count, 1);
    // 检查数组是否已满,避免越界
    if (idx >= MAX_SYSCALLS) {
        return 0;
    }

    // 将当前系统调用ID存入数组
    val->syscalls[idx] = args->id;

    return 0;
}

细节说明

  1. 原子操作逻辑:__sync_fetch_and_add会先返回当前的count值作为数组索引,再将count原子递增1,这样能保证第一个系统调用存入syscalls[0],第二个存入syscalls[1],以此类推,不会出现索引错位。
  2. 初始化方式:用zero = {0}直接初始化结构体所有成员为0,这是eBPF支持的合法语法,替代了不被支持的memset。
  3. 边界检查:必须添加idx >= MAX_SYSCALLS的判断,eBPF程序不允许数组越界,一旦触发会导致程序加载失败或运行异常。
  4. 哈希表定义:需要显式定义用于存储进程数据的哈希表data_map,确保bpf_map_lookup_or_try_init调用的是正确的map对象。

内容的提问来源于stack exchange,提问作者Afonso Pinto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:42:29