如何基于BCC/eBPF代码获取被检测系统调用的名称或ID?
获取系统调用名称/ID并实现维度统计
你的现有代码实现了按进程统计系统调用次数,要获取当前处理的系统调用ID/名称并按系统调用维度统计,可以按以下步骤修改:
1. 在BPF代码中获取系统调用ID
raw_syscalls:sys_exit 这个tracepoint内核会暴露id字段(对应系统调用号),直接通过args->id即可读取。根据你的统计需求,有两种实现方式:
方式一:统计每个系统调用的总次数
// 哈希表key为系统调用ID,value为调用次数 BPF_HASH(syscall_counts, u32, u64); TRACEPOINT_PROBE(raw_syscalls, sys_exit) { // 获取当前系统调用ID u32 syscall_id = args->id; u64 *val, zero = 0; val = syscall_counts.lookup_or_try_init(&syscall_id, &zero); if (val) { lock_xadd(val, 1); } return 0; }
方式二:统计每个进程的每个系统调用次数
如果需要同时关联进程和系统调用,用结构体作为复合key:
// 复合key:进程ID + 系统调用ID struct key { u32 pid; u32 syscall_id; }; BPF_HASH(pid_syscall_counts, struct key, u64); TRACEPOINT_PROBE(raw_syscalls, sys_exit) { u64 pid_tgid = bpf_get_current_pid_tgid(); u32 pid = pid_tgid >> 32; // 获取系统调用ID u32 syscall_id = args->id; struct key k = {.pid = pid, .syscall_id = syscall_id}; u64 *val, zero = 0; val = pid_syscall_counts.lookup_or_try_init(&k, &zero); if (val) { lock_xadd(val, 1); } return 0; }
2. 将系统调用ID转为名称(用户空间Python代码)
拿到系统调用ID后,在Python层可以通过BCC提供的syscall_name()方法直接将ID映射为对应的系统调用名称,无需手动维护映射表:
from bcc import BPF import time # 加载BPF程序 b = BPF(text=""" // 填入上面的BPF代码内容 """) def print_syscall_stats(): print("%-20s %10s" % ("系统调用名称", "调用次数")) # 遍历哈希表,转换ID为名称并打印 for k, v in b["syscall_counts"].items(): syscall_name = b.syscall_name(k.value) print("%-20s %10d" % (syscall_name, v.value)) print("-" * 30) # 定时输出统计结果 try: while True: time.sleep(2) print_syscall_stats() except KeyboardInterrupt: exit()
注意事项
- 不同CPU架构(如x86_64、ARM64)的系统调用ID存在差异,BCC的
syscall_name()会自动适配当前架构,优先使用该方法。 - 若需要统计发起的系统调用而非完成的,可替换为
raw_syscalls:sys_enter探针,同样通过args->id获取系统调用ID。
内容的提问来源于stack exchange,提问作者Afonso Pinto
相关产品推荐
相关产品推荐

