定位 printf 对象/模块

定位 printf 对象/模块

我想知道printf在我的 C 代码中执行时调用哪个内核模块。我怎样才能找到那个?比方说,当我使用时,ldd我可以找到哪些库附加到我的二进制文件中。我正在寻找类似的东西。基本上,我想学习文件结构负责 printf 。

考虑下面的代码

#include <stdio.h>
int main()
{
  int i = 0;
  int N = 100;
  while (i++ <= N) {
    printf("%d ", i);
  }
  return 0;
}

当我运行 perf 命令时perf record -e cycles -j any -a -o perf.data ./test,我在数据文件中看到以下输出

# Overhead  Command  Source Shared Object  Source Symbol                           Target Symbol                           Basic Blo
# ........  .......  ....................  ......................................  ......................................  .........
#
    21.19%  swapper  [unknown]             [k] 0000000000000000                    [k] 0000000000000000                    -
    10.98%  swapper  [kernel.vmlinux]      [k] __intel_pmu_enable_all              [k] native_write_msr                    -
    10.66%  swapper  [kernel.vmlinux]      [k] intel_pmu_lbr_enable_all            [k] __intel_pmu_enable_all              -
    10.66%  swapper  [kernel.vmlinux]      [k] native_write_msr                    [k] intel_pmu_lbr_enable_all            -
     5.00%  perf     [kernel.vmlinux]      [k] smp_call_function_single            [k] smp_call_function_single            -
     3.14%  swapper  [kernel.vmlinux]      [k] acpi_os_read_memory                 [k] acpi_os_read_memory                 -
     2.23%  swapper  [kernel.vmlinux]      [k] intel_idle                          [k] intel_idle                          -
     1.88%  swapper  [kernel.vmlinux]      [k] sched_clock                         [k] native_sched_clock                  -
     1.82%  swapper  [kernel.vmlinux]      [k] native_sched_clock                  [k] sched_clock                         -
     1.15%  swapper  [kernel.vmlinux]      [k] nmi_handle                          [k] sched_clock                         -
     1.15%  swapper  [kernel.vmlinux]      [k] native_set_fixmap                   [k] native_set_fixmap                   -
     1.09%  swapper  [kernel.vmlinux]      [k] sched_clock                         [k] nmi_handle                          -
     0.82%  swapper  [kernel.vmlinux]      [k] __x86_indirect_thunk_rax            [k] __x86_indirect_thunk_rax            -
  ...
  ...

那么,模块/文件与 关联在哪里printf? perf 输出中的第一行是什么意思?

比方说,我想分析printf为在屏幕上显示内容而执行的代码。

更新:

以下输出显示我的测试程序已链接到自定义 glibc 版本,我已使用我想要的选项从源代码重新编译了该版本。

$ ldd test
        linux-vdso.so.1 =>  (0x00007ffe26875000)
        libc.so.6 => /opt/glibc-2.23-install/libc.so.6 (0x00007f28196d5000)
        /opt/glibc-2.23-install/lib/ld-2.23.so => /lib64/ld-linux-x86-64.so.2 (0x00007f2819a76000)

答案1

您正在查看的事件都不是来自您的test程序;您需要在“命令”字段中找到一行test,然后放大它。如果运气好的话(因为perf record样本),您将看到类似的条目

   1.31%  590585  libc-2.30.so       [.] __vfprintf_internal                         [.] __vfprintf_internal
   0.18%  590585  libc-2.30.so       [.] _itoa_word                                  [.] _itoa_word
   0.18%  590585  libc-2.30.so       [.] __vfprintf_internal                         [.] _IO_file_xsputn@@GLIBC_2.2.5
   0.18%  590585  libc-2.30.so       [.] _IO_file_xsputn@@GLIBC_2.2.5                [.] __vfprintf_internal
   0.18%  590585  libc-2.30.so       [.] __strchrnul_avx2                            [.] __strchrnul_avx2

test等等,显示从(590585在我的跟踪中)到 C 库的调用,这些调用与您的printf调用相对应。

printf主要在 C 库中实现,因此您不会在内核中找到太多相关性。运行你的程序strace会产生类似的结果

...
write(1, "1 2 3 4 5 6 7 8 9 10 11 12 13 14"..., 2961 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 ) = 296
exit_group(0)                           = ?
+++ exited with 0 +++

程序中唯一与输出相关的系统调用是单个write:C 库缓冲其输出,因此所有调用printf都附加到缓冲区,并且当程序退出时,该缓冲区将在一次调用中刷新。

如果您想了解printfGNU C 库中的实现方式,请查看 中的源代码stdio-common,从printf.c。要对其printf自身进行分析,您可能会更好地为您服务gprof

相关内容