如何在Docker容器中的linux perf工具中获得调试符号?

Nat*_*ead 8 linux linux-kernel perf docker

我正在使用基于"ubuntu"标签的Docker容器,并且无法获得linux perf工具来显示调试符号.

这是我正在做的来证明这个问题.

首先,我启动一个容器,这里有一个交互式shell.

$ docker run -t -i ubuntu:14.04 /bin/bash
Run Code Online (Sandbox Code Playgroud)

然后从容器提示我安装linux perf工具.

$ apt-get update
$ apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r`
Run Code Online (Sandbox Code Playgroud)

我现在可以使用该perf工具了.我的内核是3.16.0-77-generic.

现在我将安装gcc,编译测试程序,并尝试在其下运行它perf record.

$ apt-get install -y gcc
Run Code Online (Sandbox Code Playgroud)

我将测试程序粘贴到test.c:

#include <stdio.h>

int function(int i) {
    int j;
    for(j = 2; j <= i / 2; j++) {
        if (i % j == 0) {
            return 0;
        }
    }
    return 1;
}

int main() {
    int i;
    for(i = 2; i < 100000; i++) {
        if(function(i)) {
            printf("%d\n", i);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后编译,运行和报告: perf

输出看起来像这样: 3.16.0-77-generic

即使可执行文件具有符号信息,也没有符号.

在容器外执行相同的一般步骤可以正常工作,并显示如下内容: gcc

在主机系统中,我已经通过成为root并执行以下内容来打开内核符号: perf record

如何使容器化版本正常工作并显示调试符号?

Ale*_*rov 9

使用-v /:/hostflag 运行容器并perf report在带有--symfs /host标志的容器中运行它会修复它:

perf script

为什么它不能正常工作,从/var/lib/docker/aufs类型的输出有所启发:

 96.59%  a.out  a.out              [.] function
  2.93%  a.out  [kernel.kallsyms]  [k] 0xffffffff8105144a
  0.13%  a.out  [nvidia]           [k] 0x00000000002eda57
  0.11%  a.out  libc-2.19.so       [.] vfprintf
  0.11%  a.out  libc-2.19.so       [.] 0x0000000000049980
  0.09%  a.out  a.out              [.] main
  0.02%  a.out  libc-2.19.so       [.] _IO_file_write
  0.02%  a.out  libc-2.19.so       [.] write
Run Code Online (Sandbox Code Playgroud)

注意perf report路径.这是来自主机,因此它不会存在于容器中,您需要帮助sudo perf record -a docker run -ti <container name>找到它.这可能是因为mmap事件由任何cgroup外部的perf跟踪,并且perf不会尝试重新映射路径.

另一个选择是运行perf host-side,就像-a.但是这里的集合必须是系统范围的(-v /:/host标志),因为容器是由docker守护程序进程生成的,该进程不在我们运行的docker客户端工具的进程层次结构中.

  • 谢谢,原来是这样。要添加到解决方案中,为了获得内核符号,您还需要添加:`--kallsyms=/proc/kallsyms`。 (2认同)
  • 万一它对其他人有帮助:一种更简单的方法是用-v / var / lib / docker /:/ var / lib / docker`来调用docker run,这使得perf不需要任何特殊正确解析符号的参数。 (2认同)

小智 7

另一种不需要更改容器运行方式(以便您可以分析已经运行的进程)的方法是使用 bindfs 在主机上挂载容器的根:

bindfs /proc/$(docker inspect --format {{.State.Pid}} $CONTAINER_ID)/root /foo
Run Code Online (Sandbox Code Playgroud)

然后运行 ​​perf report 作为 perf report --symfs /foo

您必须在perf record系统范围内运行,但您可以将其限制为仅收集特定容器的事件:

perf record -g -a -F 100 -e cpu-clock -G docker/$(docker inspect --format {{.Id}} $CONTAINER_ID) sleep 90
Run Code Online (Sandbox Code Playgroud)