ftrace主要是用于调试linux kernel调度相关的一个工具,也可用于分析部分kernel性能问题。

相关ftrace的介绍可以参考:kernel/msm-4.9/Documentation/trace/ftrace.txt 以及同级目录下的其他介绍文件。

kernel.org的ftrace文档也可以参考(信息较多):https://www.kernel.org/doc/html/latest/trace/ftrace.html

谷歌官网的ftrace使用教程(请自带梯子):https://source.android.google.cn/devices/tech/debug/ftrace

IBM developer的blog(介绍每个跟踪器,并且写了如何看ftrace的log,很有用,很有用,很有用):https://www.ibm.com/developerworks/cn/linux/l-cn-ftrace2/index.html

一、trace_event

trace event作为ftrace的一部分,它主要通过已有函数插桩的tracepoint,来跟踪相关事件。

例如,在进程调度关键函数:__schedule()中:

static void __sched notrace __schedule(bool preempt)
{
...
if (likely(prev != next)) {
if (!prev->on_rq)
prev->last_sleep_ts = wallclock; update_task_ravg(prev, rq, PUT_PREV_TASK, wallclock, );
update_task_ravg(next, rq, PICK_NEXT_TASK, wallclock, );
rq->nr_switches++;
rq->curr = next;
++*switch_count; trace_sched_switch(preempt, prev, next);
rq = context_switch(rq, prev, next, cookie); /* unlocks the rq */
} else {
update_task_ravg(prev, rq, TASK_UPDATE, wallclock, );
lockdep_unpin_lock(&rq->lock, cookie);
raw_spin_unlock_irq(&rq->lock);
}
...
}

利用trace event,我们能够监控某些事件,是否发生;或者在某段时间内,发生了什么。

案例:在dim idle下,耗流偏大约10mA。

dim idle是屏幕亮着,但亮度最低,系统进入idle状态,而未进入深度休眠的状态。

1、在抓取了power waveform对比正常的机器,发生耗流波形的bottom与正常的相似。但是耗流bottom很不稳定。

(异常)

(正常)

2、在检查所有外设后,并未发现有明显漏电。

3、此时,就利用ftrace的trace event,抓取在此情况下,系统到底在运行什么。

抓取方法:

Step 

Connect USB and execute below commands one by one , some times all commands in batch may not work due to adb file system issues
Verify Buffer size is reflected as the one that is set adb shell "echo 0 > /sys/kernel/debug/tracing/tracing_on"
adb shell "cat /sys/kernel/debug/tracing/tracing_on"
adb shell "echo 150000 > /sys/kernel/debug/tracing/buffer_size_kb"
adb shell "cat /sys/kernel/debug/tracing/buffer_size_kb" adb shell "echo > /sys/kernel/debug/tracing/set_event"
adb shell cat /sys/kernel/debug/tracing/set_event
adb shell "echo > /sys/kernel/debug/tracing/trace"
adb shell cat /sys/kernel/debug/tracing/trace
adb shell sync Step Enable below trace events adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_idle/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_frequency/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_frequency_switch_start/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/*/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_enq_deq_task/enable" adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_bus/bus_update_request/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/clk/clk_enable/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/clk/clk_disable/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/bw_hwmon_update/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/bw_hwmon_meas/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/memlat_dev_meas/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/memlat_dev_update/enable" adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_idle/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_frequency/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/power/cpu_frequency_switch_start/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/*/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup_new/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/sched/sched_enq_deq_task/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cluster_enter/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cluster_exit/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cluster_pred_hist/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cluster_pred_select/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cpu_idle_enter/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cpu_idle_exit/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cpu_power_select/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cpu_pred_hist/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/msm_low_power/cpu_pred_select/enable" adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_cmdbatch_queued/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_cmdbatch_submitted/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_cmdbatch_retired/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_gpubusy/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_pwr_request_state/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_pwr_set_state/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_pwrstats/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_buslevel/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_pwrlevel/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_clk/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_bus/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_rail/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/dispatch_queue_context/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_user_pwrlevel_constraint/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_clock_throttling/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_constraint/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_gpu_fault/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_cmdbatch_fault/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/adreno_cmdbatch_sync/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_issueibcmds/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_context_create/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_context_destroy/enable"
adb shell "echo 1 > /sys/kernel/debug/tracing/events/kgsl/kgsl_context_detach/enable"
adb shell "echo 1 > /d/tracing/events/msm_bus/bus_update_request/enable"
adb shell "echo 1 > /d/tracing/events/msm_bus/bus_agg_bw/enable" Step Verify the trace events and also remove any previous trace file
adb shell cat /sys/kernel/debug/tracing/set_event
adb shell rm /data/local/trace.txt Step : Start Usecase, Execute below commands with usb and disconnect usb within seconds adb shell
cd /d/tracing
sleep && echo > tracing_on && echo "" > trace && echo > tracing_on && sleep && echo > tracing_on && cat trace > /data/local/trace.txt & Step : After seconds, re-connect usb and pull the trace file adb pull /data/local/trace.txt

4、我们找到了qsee_logger在每60ms,就会运行一次。这个是一个debug qsee的log工具,应该在版本中剔除。

         <idle>-     [] dns3 17167.350289: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=
<idle>- [] dns3 17167.410357: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=
<idle>- [] dns3 17167.470370: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=
<idle>- [] dns3 17167.538874: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=
<idle>- [] dns3 17167.608888: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=
<idle>- [] dns3 17167.671269: sched_wakeup: comm=qsee_logger pid= prio= target_cpu=

5、最后使用performance ROM,验证pass。再安装qsee_logger,又出现bottom耗流不稳定的waveform。但是平均耗流仍然会比之前差的时候好。

所以,得出结论:1. qsee_logger导致bottom耗流不稳定,影响耗流

        2. 非performance ROM也影响了耗流

在此案例中,我们利用了trace event查看了系统非休眠情况下,cpu调度的相关事件,并且找出了qsee_logger影响了底电流的稳定。

二、trace function 和function_graph

需要使用这2个功能,内核配置中需要添加以下内容:CONFIG_DYNAMIC_FTRACE=y、CONFIG_FUNCTION_TRACER=y、CONFIG_IRQSOFF_TRACER=y、CONFIG_FUNCTION_PROFILER=y 和 CONFIG_PREEMPT_TRACER=y

1)trace function可以设定自己需要监测的函数,并且可以打印出其调用栈。

查看tracer,验证是否生效。

cat /d/tracing/available_tracers
blk function_graph preemptirqsoff preemptoff irqsoff function nop

1. 由于编译器有时会对函数进行重命名,因此通过使用以下命令确认(这里用例为:htc_batt_schedule_batt_info_update,看到确实后缀加了.part.8):

cat /d/tracing/available_filter_functions | grep htc_batt_schedule_batt_info_update
htc_batt_schedule_batt_info_update.part.

2. 确认存在之后,将其用作 ftrace 过滤器:

echo htc_batt_schedule_batt_info_update.part. > /d/tracing/set_ftrace_filter

3. 开启函数分析器:

echo function > /d/tracing/current_tracer

4. 开启堆栈跟踪:

echo func_stack_trace > /d/tracing/trace_options

5. 增加缓冲区大小:

echo  > /d/tracing/buffer_size_kb

6. 最后开启抓取,抓完后关闭,并获取记录文件:

echo  > /d/tracing/trace_on
执行复现问题的动作
echo > /d/tracing/trace_on
cat /d/tracing/trace > /data/local/tmp/trace

我们可以从抓取的文件中可以看到什么时刻会调用到监测的函数,并会打印出调用栈:

           <...>-  [] ...  6384.885600: htc_batt_schedule_batt_info_update.part. <-htc_battery_info_update
<...>- [] ... 6384.885612: <stack trace>
=> smb2_batt_get_prop
=> power_supply_get_property
=> status_change_work
=> process_one_work
=> worker_thread
=> kthread
=> ret_from_fork
...
...
kworker/:- [] ... 6395.535869: htc_batt_schedule_batt_info_update.part. <-htc_battery_info_update
kworker/:- [] ... 6395.535880: <stack trace>
=> smb2_usb_set_prop
=> power_supply_set_property
=> dwc3_msm_gadget_vbus_draw
=> dwc3_msm_vbus_draw_work
=> process_one_work
=> worker_thread
=> kthread
=> ret_from_fork

2)function_graph 是将调用栈打印出来,并且会显示每个阶段的运行的用时。这对于分析一些内核造成的卡顿问题有所帮助。

在上面那些config基础上,还需要打开配置:CONFIG_FUNCTION_GRAPH_TRACER=y

1. 设置tracer:

echo function_graph > /d/tracing/current_tracer

2. 最后开启抓取,抓完后关闭,并获取记录文件(设置buffer等和上面类似,不赘述):

echo  > /d/tracing/trace_on
执行复现问题的动作
echo > /d/tracing/trace_on
cat /d/tracing/trace > /data/local/tmp/trace

如下,我们可以看到每天函数的执行用时,这个时间是包含了sleep time的,所以可以用来定位系统延迟发生在哪个函数中。:

# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
) + 76.615 us | } /* vfs_open */
) 0.156 us | open_check_o_direct();
) | terminate_walk() {
) 0.104 us | drop_links.isra.();
) | dput() {
) | __might_sleep() {
) 0.156 us | ___might_sleep();
) 3.750 us | }
) 0.105 us | __rcu_read_lock();
) 0.156 us | __rcu_read_unlock();
) + 17.396 us | }
) | mntput() {
) | mntput_no_expire() {
) 0.156 us | __rcu_read_lock();
) 0.833 us | preempt_count_add();
) 0.208 us | preempt_count_sub();
) 0.157 us | __rcu_read_unlock();
) + 18.229 us | }
) + 21.875 us | }
) | dput() {
) | __might_sleep() {
) 0.157 us | ___might_sleep();
) 3.854 us | }
) 0.104 us | __rcu_read_lock();
) 0.156 us | __rcu_read_unlock();
) + 15.990 us | }

其中计时前面的符号是一种提醒,让我们能注意到哪些地方的用时比较长,可能存在问题:

  + means that the function exceeded  usecs.
! means that the function exceeded usecs.
# means that the function exceeded usecs.
* means that the function exceeded msecs.
@ means that the function exceeded msecs.
$ means that the function exceeded sec.

3)动态ftrace

由于上面两种方法都会监测很多其他函数,会对系统造成较大负担。所以,需要使用动态过滤监测函数的方式。

如果我们想只跟踪特定函数,可以把需要配置跟踪的函数写入到节点:

echo htc_batt_schedule_batt_info_update.part. > /d/tracing/set_ftrace_filter ------- function tracer
echo htc_batt_schedule_batt_info_update.part. > /d/tracing/set_graph_function ------ function_graph tracer

或者想把一些函数排除在外,可以写入如下节点:

/sys/kernel/debug/tracing/set_ftrace_notrace ------- function tracer
/sys/kernel/debug/tracing/set_graph_notrace ------ function_graph tracer

BTW,trace抓取之后,想再次抓取,默认是会把上次抓取的也包含在内的。所以,如果不需要上一次的信息,需要清空trace之后,重新再开始抓取:

echo '' > /d/tracing/trace 

Ftrace的部分使用方法的更多相关文章

  1. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  2. Linux内核调试方法总结之ftrace

    ftrace [用途] ftrace包含一系列跟踪器,用于不同的场合,比如跟踪内核函数调用(function tracer).跟踪上下文切换(sched_switch tracer).查看中断被关闭的 ...

  3. ftrace 使用方法

    1. 追蹤Kernel function (以schedule()示範) 先至 /sys/kernel/debug/tracing# cat available_tracers 確定有無 函式追蹤器( ...

  4. LISA介绍及其使用方法

    LISA是ARM公司开发的一款开源工具.在内核开发过程中,苦于无法针对修改内容进行一些量化或者可视化结果的测量,而无感.LISA对于模型调优,回归测试都有较强的支持. 什么是LISA? LISA是Li ...

  5. ftrace的使用【转】

    转自:http://blog.csdn.net/cybertan/article/details/8258394 This article explains how to set up ftrace ...

  6. 利用ftrace跟踪内核static tracepoint——实例writeback event

    摘要:和很多linux内核子系统一样,static tracepoint有很多层次,其中某个层次都展示给不同层次的开发者来满足他们的不同需求.关于linux tracepoint的详细信息,我们可以在 ...

  7. ftrace利器之trace-cmd和kernelshark

    关键词:ftrace.trace-cmd.kernelshark. trace-cmd是设置读取ftrace的命令行工具,kernelshark既可以记录数据,也可以图形化分析结果. trace-cm ...

  8. 利用ftrace跟踪内核static tracepoint

    摘要:和很多linux内核子系统一样,static tracepoint有很多层次,其中某个层次都展示给不同层次的开发者来满足他们的不同需求.关于linux tracepoint的详细信息,我们可以在 ...

  9. 【转】ftrace 简介

    ftrace 简介 ftrace 的作用是帮助开发人员了解 Linux 内核的运行时行为,以便进行故障调试或性能分析. 最早 ftrace 是一个 function tracer,仅能够记录内核的函数 ...

随机推荐

  1. 推荐算法_CIKM-2019-AnalytiCup 冠军源码解读

    最近在帮一初创app写推荐系统,顺便学习一波用户兴趣高速检索的冠军算法. 写总结前贴出冠军代码的git地址:https://github.com/ChuanyuXue/CIKM-2019-Analyt ...

  2. JAVA知识总结(三):继承和访问修饰符

    今天乘着还有一些时间,把上次拖欠的面向对象编程三大特性中遗留的继承和多态给简单说明一下.这一部分还是非常重要的,需要仔细思考. 继承 继承:它是一种类与类之间的关系,通过使用已存在的类作为基础来建立新 ...

  3. Spring Cloud 系列之 Config 配置中心(三)

    本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) 本篇文章讲解 Conf ...

  4. [uva_la7146 Defeat the Enemy(2014 shanghai onsite)]贪心

    题意:我方n个军队和敌方m个军队进行一对一的对战,每个军队都有一个攻击力和防御力,只要攻击力不小于对方就可以将对方摧毁.问在能完全摧毁敌方的基础上最多能有多少军队不被摧毁. 思路:按防御力从大到小考虑 ...

  5. [hdu5389 Zero Escape]数根的性质,DP

    题意:把n个数(1-9)放到A集合和B集合里面去,使得A集合里面的数的数根为a,B集合里面的数的数根为b,也可以只放在A或B任一个集合里面.求方法总数.比如A={2,4,5},则A的数根为[2+4+5 ...

  6. [hdu3572]最大流(dinic)

    题意:有m台机器,n个任务,每个任务需要在第si~ei天之间,且需要pi天才能完成,每台机器每天只能做一个任务,不同机器每天不能做相同任务,判断所有任务是否可以做完. 思路: 把影响答案的对象提取出来 ...

  7. 手机app传统邀请码安装与免邀请码安装区别,如何选择呢?

    App 邀请机制是每个产品几乎必做的功能点,它一般以两种形式存在:一是作为常置功能用于推荐,二是作为裂变活动用于邀请. 无论以哪种形式出现,都可以归为社交分享的一种表现方式.相较于营销推广,邀请好友机 ...

  8. python 基础知识6-文件操作

    1.只读文件 #以文本打开文件'r' f = open('C:\\Users\\Administrator\\Desktop\\Python\\f.txt',mode='r',encoding='ut ...

  9. Linux --常见Linux目录名称

    Linux文件系统结构是从Unix文件结构演进过来的,在Linux文件系统中,通用的文件系统中,通用的目录名用于表示一些常见的功能.如下所示: 目录 用途 / 虚拟目录的根目录,通常不会再这里存储文件 ...

  10. select 标签的数据绑定

    修改数据的页面 进入页面绑定select的值 会value绑定但是没有显示相应的option <script> $("#id option[value=${item.decora ...