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 虚拟机中完成的。
有没有办法知道在某个事件期间调用了哪些内核函数。
例如,如果我按键盘上的任意键,我想知道所有内核函数和设备驱动程序函数都被调用了什么——在字符出现在屏幕上之前(与我键入的键对应的字符)键盘)。
我想把完整的流程转储到某个地方,稍后再检查。我说的是内核-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 虚拟机中完成的。