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

使用Intel PT追踪时,perf过滤器在容器内是否生效?

perf ftrace过滤器在Docker容器中配合Intel PT追踪失效的问题分析与解决思路

问题背景

我开发了一个直接调用perf_event_open()的用户态工具,用Intel PT追踪程序控制流,最近加了ftrace过滤器来只追踪目标代码段。在Debian 12.9(内核6.1.0-31-amd64)主机上测试正常:执行命令

perf record -e intel_pt//u -v --filter 'filter 0x0000000000004000/0x0000000000015759@/bin/ls' /bin/ls -- /dev/null

生成的perf.data里有130个TNT包和190个TIP包,符合预期。但在开启PERFMON权限的Docker容器里,即使/bin/ls的可执行段偏移和主机一致,执行相同命令后,perf.data里只有非控制流PT数据包,完全没有TNT和TIP包。无ftrace过滤器时,Intel PT在容器里能正常工作,问题只和过滤器有关。

核心原因推测

perf的ftrace过滤器是基于内核的文件系统视图工作的:

  • 容器内的/bin/ls属于容器镜像的文件系统,和主机的/bin/ls是两个不同的文件,inode不一致。
  • 过滤器里的@/bin/ls会被内核解析为主机的/bin/ls路径,导致容器内进程的代码段完全不匹配过滤规则,所以没有控制流数据包被捕获。
  • 尝试指定主机路径或复制主机ls到容器对应路径无效,是因为容器的文件系统隔离机制,内核依然无法正确关联容器内进程与主机路径的文件。

解决思路

  1. 通过进程PID指定过滤器
    绕开路径匹配的问题,直接绑定到目标进程的地址空间:

    # 容器内后台启动目标进程
    /bin/ls -- /dev/null &
    TARGET_PID=$!
    # 读取可执行段的起始地址和长度(容器内执行)
    EXEC_START=$(readelf -l /bin/ls | grep -E 'LOAD.*R E' | awk '{print $4}')
    EXEC_LEN=$(readelf -l /bin/ls | grep -E 'LOAD.*R E' | awk '{print $6}')
    # 用PID指定过滤器追踪
    perf record -e intel_pt//u -v --filter "filter 0x$EXEC_START/0x$EXEC_LEN@$TARGET_PID" --pid $TARGET_PID
    
  2. 绑定挂载主机文件到容器
    将主机的/bin/ls绑定挂载到容器内的相同路径,让容器内的/bin/ls和主机的是同一个文件(inode一致):

    docker run -it --cap-add=PERFMON -v /bin/ls:/bin/ls debian:12.9
    

    此时再执行原perf命令,过滤器就能正确匹配。

  3. 调试过滤器加载状态
    通过perf的verbose输出验证过滤器是否正确解析:

    perf record -e intel_pt//u -v --filter 'filter 0x4000/0x15759@/bin/ls' /bin/ls -- /dev/null 2>&1 | grep -i filter
    

    观察输出中过滤器的路径匹配结果,确认是否存在路径识别错误。

结论

perf的ftrace过滤器在容器环境中应该正常工作,但存在路径解析的兼容性问题,核心是内核的过滤器依赖主机文件系统视图,而容器内的路径对应的文件与主机路径文件不匹配。通过PID绑定或绑定挂载主机文件的方式,可以有效规避这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:19:55