Ubuntu 21.04容器中perf测试26: Object code reading失败原因及测试内容咨询
我来帮你拆解这个问题,先从perf test 26的测试内容说起,再分析容器里失败的原因:
关于Object code reading测试的具体内容
这个测试是用来验证perf工具最核心的目标代码读取与符号解析能力,核心流程大概是这样的:
- 尝试访问系统内核模块目录(
/lib/modules/内核版本),加载内核模块的符号信息,为内核态代码解析做准备 - 尝试打开
/proc/kcore(内核内存镜像文件),用于读取内核空间的代码与符号 - 解析用户态性能事件(比如日志里的
cycles:u),通过mmap映射相关内存区域 - 定位到用户态库(比如
libc-2.33.so)的特定内存地址,读取对应的机器码并验证解析的正确性
简单来说,这个测试是perf后续所有采样、分析功能的基础,确保它能正确识别并读取用户态和内核态的目标代码。
容器中测试失败的核心原因分析
从你给出的日志里,能看到几个关键的问题点:
内核模块目录缺失
maps__set_modules_path_dir: cannot open /lib/modules/5.11.0-22-generic dir
Docker容器默认不会自动挂载宿主机的/lib/modules目录,哪怕加了--privileged参数也不行。perf需要这个目录下的内核模块元数据来完成符号解析,缺失后会直接影响内核态代码的读取流程。/proc/kcore访问受限Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO capability to access.
虽然--privileged会赋予容器几乎所有权限,但/proc/kcore属于宿主机内核的敏感资源,容器环境下即使有CAP_SYS_RAWIO,也可能因为内核的安全机制(比如user namespace隔离、seccomp限制)无法正常访问。/proc文件系统信息不匹配/proc/{kallsyms,modules} inconsistency while looking for "[bpf]" module!
容器里的/proc是从宿主机挂载的,但容器本身不会加载宿主机的全部内核模块,导致/proc/kallsyms(内核符号表)和/proc/modules(加载的模块列表)信息不匹配。perf在验证这两个文件的一致性时出错,进而打乱了后续的符号解析逻辑。用户态代码读取最终失败
前面的一系列环境异常,导致perf的符号解析流程出现故障,哪怕最后定位到了libc-2.33.so的内存地址,也无法正确读取或验证对应的机器码,最终测试子进程返回-1,测试失败。
可能的解决方向
如果需要让这个测试在容器中通过,可以尝试以下几个操作:
- 挂载宿主机的内核模块目录:启动容器时添加
-v /lib/modules:/lib/modules:ro参数,让容器能访问到宿主机的内核模块元数据 - 调整容器安全配置:除了
--privileged,可以额外添加--cap-add SYS_RAWIO(确保权限生效),同时关闭seccomp限制:--security-opt seccomp=unconfined - 使用宿主机的perf二进制:挂载宿主机的
/usr/bin/perf到容器内(-v /usr/bin/perf:/usr/bin/perf),避免容器内的perf版本和宿主机内核不匹配的问题(perf和内核版本强绑定)
内容的提问来源于stack exchange,提问作者nnnmmm




