Linux 内核函数调用流程

Linux kernel function call flow

有没有办法知道在某个事件期间调用了哪些内核函数。

例如,如果我按键盘上的任意键,我想知道所有内核函数和设备驱动程序函数都被调用了什么——在字符出现在屏幕上之前(与我键入的键对应的字符)键盘)。

我想把完整的流程转储到某个地方,稍后再检查。我说的是内核-space 函数——不是用户-space 函数。

I want to know what all kernel functions and device driver functions are getting called

显然,跟踪的完整性取决于它从哪里开始。这取决于你。

您可以通过方便的 trace-cmd 追踪您想要的东西。例如。你可以获得功能图。首先你需要根据自己的需要确定一些切入点。
如果是关于键盘按键,你需要找到它的驱动程序和一些相关的功能。

示例:
经典 AT 和 PS/2 键盘驱动程序 atkbd has interrupt function atkbd_interrupt。看看有没有这样的trace点:

trace-cmd list -f | grep atkbd_int

然后开始录制:

trace-cmd record -p function_graph -g atkbd_interrupt &

按一些键停止录音:fg 然后 Ctrl+C。现在可以得到函数图:

trace-cmd report | vim -

它会是这样的:

CPU 1 is empty
CPU 2 is empty
CPU 3 is empty
cpus=4
          <idle>-0     [000] 1095787.266859: funcgraph_entry:                   |  atkbd_interrupt() {
          <idle>-0     [000] 1095787.266863: funcgraph_entry:                   |    input_event() {
          <idle>-0     [000] 1095787.266864: funcgraph_entry:        0.215 us   |      _raw_spin_lock_irqsave();
          <idle>-0     [000] 1095787.266866: funcgraph_entry:        0.386 us   |      input_handle_event();
          <idle>-0     [000] 1095787.266867: funcgraph_entry:        0.163 us   |      _raw_spin_unlock_irqrestore();
          <idle>-0     [000] 1095787.266868: funcgraph_exit:         3.882 us   |    }
          <idle>-0     [000] 1095787.266869: funcgraph_entry:                   |    input_event() {
          <idle>-0     [000] 1095787.266869: funcgraph_entry:        0.123 us   |      _raw_spin_lock_irqsave();
          <idle>-0     [000] 1095787.266870: funcgraph_entry:                   |      input_handle_event() {
          <idle>-0     [000] 1095787.266871: funcgraph_entry:                   |        add_input_randomness() {
          <idle>-0     [000] 1095787.266871: funcgraph_entry:                   |          add_timer_randomness() {
          <idle>-0     [000] 1095787.266872: funcgraph_entry:                   |            mix_pool_bytes() {
          <idle>-0     [000] 1095787.266872: funcgraph_entry:        0.327 us   |              _raw_spin_lock_irqsave();
          <idle>-0     [000] 1095787.266873: funcgraph_entry:        0.877 us   |              _mix_pool_bytes();
          <idle>-0     [000] 1095787.266875: funcgraph_entry:        0.163 us   |              _raw_spin_unlock_irqrestore();
          <idle>-0     [000] 1095787.266876: funcgraph_exit:         3.628 us   |            }
          <idle>-0     [000] 1095787.266876: funcgraph_entry:                   |            credit_entropy_bits() {
          <idle>-0     [000] 1095787.266877: funcgraph_entry:                   |              __wake_up() {
          <idle>-0     [000] 1095787.266877: funcgraph_entry:        0.229 us   |                _raw_spin_lock_irqsave();
          <idle>-0     [000] 1095787.266878: funcgraph_entry:        0.120 us   |                __wake_up_common();
          <idle>-0     [000] 1095787.266879: funcgraph_entry:        0.135 us   |                _raw_spin_unlock_irqrestore();
          <idle>-0     [000] 1095787.266880: funcgraph_exit:         2.719 us   |              }
          <idle>-0     [000] 1095787.266880: funcgraph_entry:        0.108 us   |              kill_fasync();
          <idle>-0     [000] 1095787.266881: funcgraph_exit:         4.833 us   |            }
          <idle>-0     [000] 1095787.266882: funcgraph_exit:       + 10.249 us  |          }
          <idle>-0     [000] 1095787.266882: funcgraph_exit:       + 11.186 us  |        }
          <idle>-0     [000] 1095787.266883: funcgraph_entry:        0.237 us   |        atkbd_event();
          <idle>-0     [000] 1095787.266884: funcgraph_exit:       + 13.347 us  |      }
          <idle>-0     [000] 1095787.266884: funcgraph_entry:        0.138 us   |      _raw_spin_unlock_irqrestore();
          ........                                                         

例如,这只是一小段痕迹。我是在我的 qemu 虚拟机中完成的。