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

使用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,需要确保:

  1. 内核版本的task_struct中pid字段的偏移量正确,可以用bpftool btf dump file /sys/kernel/btf/vmlinux format c | grep -A5 -B5 'pid'查看偏移。
  2. 使用bpf_probe_read()函数安全读取,避免触发BPF验证器错误,示例:
u32 pid;
bpf_probe_read(&pid, sizeof(pid), &current->pid);

但这种方法兼容性差,优先推荐使用官方辅助函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:31:16