赞
踩
接之前文章 《ftrace tracers 之 function、function_graph 使用笔记(一)》
先从简单的代码流程跟踪使用学起,看下具体如何使用 function
和 function_graph
。
1、function
跟踪器可以跟踪内核函数的执行情况,可以通过 set_ftrace_filter
显式指定要跟踪的函数。可以用于跟踪内核某个函数被调用的频次,在被调用的情况。
2、function_graph
与function
跟踪器类似,只是function
跟踪器在函数的入口处探测函数,而function_graph
跟踪器在函数的入口和出口处跟踪,然后使得其提供了绘制类似于 C 代码源的函数调用图的能力。可以通过 set_graph_function
显式指定要生成调用流程图的函数。因此可以用于跟踪内核某个函数内部调用的子函数流程及耗时。
基于 ftrace 的内核函数调用跟踪整体架构:
一般用作产品正式发布的版本,默认tracer
应该是 nop
,如果想要使用 其他 tracer
需要打开对应的内核配置宏才行。
比如,今天我们使用到的 function
、function_graph
,需使能如下对应配置内核宏:
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
如果配置ok,在系统中会看到类似如下信息:
root:/sys/kernel/tracing # cat available_tracers
function_graph function nop ...
接下来就可以正常使用 function
和 function_graph
了。
我们主要是为了单个事件或单个函数跟踪,所以排除其他多余的信息干扰。如果是做具体问题分析,则就要根据实际需要进行设置了。
root:/sys/kernel/tracing # echo 0 > tracing_on
root:/sys/kernel/tracing # echo > set_event
root:/sys/kernel/tracing # echo > trace
sched_wakeup
这个跟踪事件/跟踪点,跟踪函数为例:root:/sys/kernel/tracing # cat events/sched/sched_wakeup/format name: sched_wakeup ID: 87 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:char comm[16]; offset:8; size:16; signed:0; field:pid_t pid; offset:24; size:4; signed:1; field:int prio; offset:28; size:4; signed:1; field:int success; offset:32; size:4; signed:1; field:int target_cpu; offset:36; size:4; signed:1; print fmt: "comm=%s pid=%d prio=%d target_cpu=%03d", REC->comm, REC->pid, REC->prio, REC->target_cpu
说明:
1、以上 格式的 sched_wakeup 打印信息,由该跟踪点对应的处理函数 sched_wakeup_handler
处理生成。
2、针对 sched_wakeup 进行跟踪的函数为:__traceiter_sched_wakeup
。
function
跟踪看下进行跟踪 sched_wakeup 事件的函数 __traceiter_sched_wakeup
被调用情况。root:/sys/kernel/tracing # echo function > current_tracer
root:/sys/kernel/tracing # echo 1 > options/func_stack_trace
root:/sys/kernel/tracing # echo __traceiter_sched_wakeup > set_ftrace_filter
root:/sys/kernel/tracing # cat set_ftrace_filter
__traceiter_sched_wakeup
ftrace 设置过滤函数过程需要一点时间,稍等片刻。然后:
root:/sys/kernel/tracing # echo 1 > tracing_on
因为是休眠/唤醒相关的函数,所以需要人为制造一次待机/唤醒动作,然后才能看到跟踪日志,如:
root:/sys/kernel/tracing # cat trace # tracer: function # # entries-in-buffer/entries-written: 1035/1035 #P:8 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | kworker/0:0-14171 [000] .... 78999.634206: lpi_pinctrl_runtime_resume: lpi_pinctrl_runtime_resume: enter kworker/0:0-14171 [000] .... 78999.634220: lpi_pinctrl_runtime_resume: lpi_pinctrl_runtime_resume: exit ... kworker/0:0-14171 [000] .... 78999.634759: swrm_runtime_suspend: swrm_runtime_suspend: pm_runtime: suspend done state: 3 ... kworker/0:0-14171 [000] .... 78999.761684: lpi_pinctrl_runtime_suspend: lpi_pinctrl_runtime_suspend: enter kworker/0:0-14171 [000] .... 78999.763192: lpi_pinctrl_runtime_suspend: lpi_pinctrl_runtime_suspend: exit
被调用的地方和过程有很多,以上只提取了一部分信息,可以看到 一次对称的 resume / suspend 过程, 在此过程,__traceiter_sched_wakeup
有被 pinctrl 调用的情况。
function_graph
跟踪 看下进行跟踪 sched_wakeup 事件的函数 __traceiter_sched_wakeup
调用关系情况。通过function
跟踪看下进行跟踪sched_wakeup 的函数 __traceiter_sched_wakeup
被调用情况。
root:/sys/kernel/tracing # echo > set_ftrace_filter
root:/sys/kernel/tracing # echo function_graph > current_tracer
root:/sys/kernel/tracing # echo 1 > options/funcgraph-tail
root:/sys/kernel/tracing # echo __traceiter_sched_wakeup > set_graph_function
root:/sys/kernel/tracing # cat set_graph_function
__traceiter_sched_wakeup
注意,使用 echo > set_ftrace_filter
清除已指定的函数是必须要的操作,否则无法进行 function_graph
绘制。使用echo 1 > options/funcgraph-tail
可以增加函数尾部注释。
ftrace 设置过滤函数过程需要一点时间,稍等片刻。同样,使能 tracing_on 之后,需要人为制造一次休眠唤醒,然后 cat 抓取日志:
root:/sys/kernel/tracing # echo 1 > tracing_on root:/sys/kernel/tracing # cat trace # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | ------------------------------------------ 1) kworker-14181 => kworker-14620 ------------------------------------------ 1) | /* lpi_pinctrl_runtime_suspend: enter */ ------------------------------------------ 1) kworker-14181 => kworker-14620 ------------------------------------------ 1) | /* lpass_hw_vote_unprepare: core vote clk_id 10a */ 1) | /* digital_cdc_rsc_mgr_hw_vote_disable */ 1) | /* lpi_pinctrl_runtime_suspend: exit */
以上只是部分信息节选,可能函数 __traceiter_sched_wakeup 本身就是 ftrace 进行跟踪 sched_wakeup 这个 event 的,函数本身并没有复杂的调用流程关系,所以我们看到的 function关系、 function_graph关系也都比较简单。
以上相当于使用 ftrace 跟踪了一个 ftrace 的跟踪事件的函数,^_^
。
下面以一个常规内核函数为例再看下。
pm_wakeup_ws_event
为例:function
跟踪 pm_wakeup_ws_event
。root:/sys/kernel/tracing # echo 0 > tracing_on
root:/sys/kernel/tracing # echo > set_event
root:/sys/kernel/tracing # echo > trace
root:/sys/kernel/tracing # echo > set_graph_function
root:/sys/kernel/tracing # echo function > current_tracer
root:/sys/kernel/tracing # echo 1 > options/func_stack_trace
root:/sys/kernel/tracing # echo pm_wakeup_ws_event > set_ftrace_filter
root:/sys/kernel/tracing # cat set_ftrace_filter
pm_wakeup_ws_event
root:/sys/kernel/tracing # echo 1 > tracing_on
ftrace 设置过滤函数过程需要一点时间,稍等片刻。然后:
root:/sys/kernel/tracing # cat trace # tracer: function # # entries-in-buffer/entries-written: 0/0 #P:8 # # _-----=> irqs-off # / _----=> need-resched # | / _---=> hardirq/softirq # || / _--=> preempt-depth # ||| / delay # TASK-PID CPU# |||| TIMESTAMP FUNCTION # | | | |||| | | ... kworker/1:2-16429 [001] .... 127214.479918: lpi_pinctrl_runtime_suspend: lpi_pinctrl_runtime_suspend: enter ... kworker/1:2-16429 [001] .... 127214.483106: lpi_pinctrl_runtime_suspend: lpi_pinctrl_runtime_suspend: exit ...
function_graph
跟踪 pm_wakeup_ws_event
。root:/sys/kernel/tracing # echo 0 > tracing_on
root:/sys/kernel/tracing # echo > set_event
root:/sys/kernel/tracing # echo > trace
root:/sys/kernel/tracing # echo > set_ftrace_filter
root:/sys/kernel/tracing # echo function_graph > current_tracer
root:/sys/kernel/tracing # echo 1 > options/funcgraph-tail
root:/sys/kernel/tracing # echo pm_wakeup_ws_event> set_graph_function
root:/sys/kernel/tracing # cat set_graph_function
pm_wakeup_ws_event
root:/sys/kernel/tracing # echo 1 > tracing_on
root:/sys/kernel/tracing # cat trace
ftrace 设置过滤函数过程需要一点时间,稍等片刻。然后:
root:/sys/kernel/tracing # cat trace root:/sys/kernel/tracing # cat trace| head # tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | ------------------------------------------ 1) kworker-14620 => HwBinde-4845 ------------------------------------------ 1) | pm_wakeup_ws_event() { 1) 1.928 us | _raw_spin_lock_irqsave(); 1) | wakeup_source_activate() { 1) | ktime_get() { 1) 1.198 us | arch_counter_read(); 1) 3.594 us | } /* ktime_get */ 1) 6.615 us | } /* wakeup_source_activate */ 1) | s2idle_wake() { 1) 1.146 us | _raw_spin_lock_irqsave(); 1) 1.145 us | _raw_spin_unlock_irqrestore(); 1) 5.469 us | } /* s2idle_wake */ 1) | wakeup_source_deactivate() { 1) | ktime_get() { 1) 1.197 us | arch_counter_read(); 1) 3.333 us | } /* ktime_get */ 1) 1.146 us | del_timer(); 1) 7.865 us | } /* wakeup_source_deactivate */ 1) 1.146 us | _raw_spin_unlock_irqrestore(); 1) + 38.334 us | } /* pm_wakeup_ws_event */ 1) | pm_wakeup_ws_event() { 1) 1.562 us | _raw_spin_lock_irqsave(); 1) | wakeup_source_activate() { 1) | ktime_get() { 1) 1.198 us | arch_counter_read(); 1) 3.386 us | } /* ktime_get */ 1) 5.625 us | } /* wakeup_source_activate */ 1) | s2idle_wake() { 1) 1.146 us | _raw_spin_lock_irqsave(); 1) 1.146 us | _raw_spin_unlock_irqrestore(); 1) 5.365 us | } /* s2idle_wake */ 1) | wakeup_source_deactivate() { 1) | ktime_get() { 1) 1.146 us | arch_counter_read(); 1) 3.281 us | } /* ktime_get */ 1) 1.198 us | del_timer(); 1) 7.761 us | } /* wakeup_source_deactivate */ 1) 1.875 us | _raw_spin_unlock_irqrestore(); 1) + 30.156 us | } /* pm_wakeup_ws_event */ ------------------------------------------ root:/sys/kernel/tracing # ps -A| grep 14620 root 14620 2 0 0 worker_thread 0 I [kworker/1:2-events]
/** drivers/base/power/wakeup.c * pm_wakeup_ws_event - Notify the PM core of a wakeup event. * @ws: Wakeup source object associated with the event source.与事件源关联的唤醒源对象。 * @msec: Anticipated event processing time (in milliseconds).预期的事件处理时间(以毫秒为单位)。 * @hard: If set, abort suspends in progress and wake up from suspend-to-idle. * * Notify the PM core of a wakeup event whose source is @ws that will take approximately @msec milliseconds to be processed by the kernel. If @ws is not active, activate it. If @msec is nonzero, set up the @ws' timer to execute pm_wakeup_timer_fn() in future. * 通知 PM 内核有一个唤醒事件,它的源是 @ws,内核处理大约需要 @msec 毫秒。 如果@ws 未激活,请激活它。 如果@msec 不为零,则设置@ws 的计时器以在将来执行 pm_wakeup_timer_fn()。 * * It is safe to call this function from interrupt context. 在中断上下文调用这个函数是安全的。 */ void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard) { unsigned long flags; unsigned long expires; if (!ws) return; spin_lock_irqsave(&ws->lock, flags); wakeup_source_report_event(ws, hard); if (!msec) { wakeup_source_deactivate(ws); goto unlock; } expires = jiffies + msecs_to_jiffies(msec); if (!expires) expires = 1; if (!ws->timer_expires || time_after(expires, ws->timer_expires)) { mod_timer(&ws->timer, expires); ws->timer_expires = expires; } unlock: spin_unlock_irqrestore(&ws->lock, flags); } EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
ref:
https://baijiahao.baidu.com/s?id=1727506047428430246&wfr=spider&for=pc
https://support.huaweicloud.com/moredocuments-kunpengdevps/kunpengsys_06_0100_0.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。