使用BPF从task_struct读取pid时出现内联汇编错误求助
解决BPF读取task_struct->pid时的编译错误与警告问题
问题场景
我正在做BPF实验,目标是在内核环境中从task_struct结构体读取并打印PID值,编写了如下基于BCC的Python程序:
from __future__ import print_function from bcc import BPF prog = """ #include <linux/sched.h> int trace(void *ctx) { int pid = current->pid; bpf_trace_printk("val (%d)", pid); return 0; } """ b = BPF(text=prog) b.attach_kprobe(event="<a kernel function>", fn_name="trace") print("PID MESSAGE") try: b.trace_print(fmt="{1} {5}") except KeyboardInterrupt: exit()
运行报错
执行程序后出现编译警告与错误:
#define __HAVE_BUILTIN_BSWAP16__ ^ <command line>:3:9: note: previous definition is here #define __HAVE_BUILTIN_BSWAP16__ 1 ^ 3 warnings generated. error: invalid operand in inline asm: 'movq %gs:${1:P}, $0' at line 2149017352
解决方案
1. 处理宏重复定义警告
__HAVE_BUILTIN_BSWAP16__重复定义是因为内核头文件与BCC自带头文件的宏冲突,在BPF程序开头添加#undef即可消除警告:
#undef __HAVE_BUILTIN_BSWAP16__
2. 修复内联汇编错误(核心问题)
错误的根源有两个,需要同时修正:
- 占位符内核函数未替换:代码中的
<a kernel function>是占位符,必须替换为真实存在且可挂载kprobe的内核函数,比如sys_clone、do_sys_open或schedule。 - 直接访问
current->pid的兼容性问题:不同内核版本中task_struct结构可能变化,且BPF验证器可能限制直接访问内核结构体字段。改用BPF官方提供的bpf_get_current_pid_tgid()辅助函数,该函数安全且兼容性更强。
注意:内核中current->pid对应线程ID,current->tgid对应进程ID。bpf_get_current_pid_tgid()返回64位值,高32位是线程ID,低32位是进程ID,按需取值即可。
修改后的完整代码
from __future__ import print_function from bcc import BPF prog = """ #undef __HAVE_BUILTIN_BSWAP16__ #include <linux/sched.h> int trace(void *ctx) { // 取线程ID(对应原代码的current->pid) u32 pid = (bpf_get_current_pid_tgid() >> 32); // 如果要取进程ID(对应current->tgid),用下面这行: // u32 pid = bpf_get_current_pid_tgid() & 0xFFFFFFFF; bpf_trace_printk("val (%d)", pid); return 0; } """ b = BPF(text=prog) # 替换为真实内核函数,这里用sys_clone示例 b.attach_kprobe(event="sys_clone", fn_name="trace") print("PID MESSAGE") try: b.trace_print(fmt="{1} {5}") except KeyboardInterrupt: exit()
额外说明
如果一定要直接访问current->pid,需要确保:
- 内核版本的
task_struct中pid字段的偏移量正确,可以用bpftool btf dump file /sys/kernel/btf/vmlinux format c | grep -A5 -B5 'pid'查看偏移。 - 使用
bpf_probe_read()函数安全读取,避免触发BPF验证器错误,示例:
u32 pid; bpf_probe_read(&pid, sizeof(pid), ¤t->pid);
但这种方法兼容性差,优先推荐使用官方辅助函数。
内容的提问来源于stack exchange,提问作者Franc
相关产品推荐
相关产品推荐

