CONFIG_SCHED_TRACER
... (下面还有几个追踪器的选项,可以根据自己的需要选择)
depends on !X86_32 || !CC_OPTIMIZE_FOR_SIZE
-*- Debug Filesystem
到该目录。
或者我们可以使用官方挂载办法后建立一个软连接:
# mount -t debugfs nodev /sys/kernel/debug
# ln -s /sys/kernel/debug /debug
在老一点版本的内核上tracing目录下有tracing_enabled,需要给tracing_enabled和tracing_on同时赋值 1 才能打开追踪,而在比较新的内核上已经去掉 tracing_enabled ,我们只需要控制tracing_on 即可打开关闭追踪。
#echo 1 > tracing_on // 打开跟踪
# echo 0 > tracing_on // 关闭跟踪
注:对于为什么去掉 tracing_enabled 我问过 Ftrace 的维护人Steven Rostedt,他说使用 tracing_on 可以快速的打开 Ftrace 的追踪,这让 tracing_enabled 显得很轻量级或者说显得比较冗余,下面可以会说到,我们写内核程序时可以使用Ftrace 提供的内核函数 tracing_on() or tracing_off() 直接打开追踪,这其实就是使用的 tracing_on ,所以在新内核中 tracing_enabled 这个看起来比较冗余的选项已经被删除。
使用 echo pid > set_ftrace_pid 来追踪指定的进程!
我们写程序时可以使用getpid 获取进程PID,然后使用 write 将pid 写入 /debug/tracing/set_ftrace_pid ,并使用write 写1 到 tracing_on 打开追踪(因为在用户空间使用不了tracing_on函数),此时即可追踪当前这个进程。
...(省略追踪过程)
# cat trace | head -10
# tracer: nop
#TASK-PID CPU# TIMESTAMP FUNCTION
# || | |
bash-2613 [001] 425.078164: sched_wakeup: task bash:2613 [120] success=0 [001]
bash-2613 [001] 425.078184: sched_wakeup: task bash:2613 [120] success=0 [001]
...
...
# cat trace | head -10
# tracer: nop
#TASK-PID CPU# TIMESTAMP FUNCTION
# | | | |
events/0-9 [000] 638.042792: sched_switch: task events/0:9 [120] (S) ==> kondemand/0:1305 [120]
ondemand/0-1305 [000] 638.042796: sched_stat_wait: task: restorecond:1395 wait: 15023 [ns]
...
...
# cat trace | head -10
# tracer: nop
#TASK-PID CPU# TIMESTAMP FUNCTION
# | | | |
cpid-1470 [001] 794.947181: kfree: call_site=ffffffff810c996d ptr=(null)
acpid-1470 [001] 794.947182: sys_read -> 0x1
acpid-1470 [001] 794.947183: sys_exit: NR 0 = 1
...
将要跟踪的函数写入文件 set_ftrace_filter ,将不希望跟踪的函数写入文件 set_ftrace_notrace。通常直接操作文件 set_ftrace_filter 就可以了.
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> MODULE_LICENSE("GPL"); static int ftrace_demo_init(void) { trace_printk("Can not see this in trace unless loaded for the second time\n"); return 0; } static void ftrace_demo_exit(void) { trace_printk("Module unloading\n"); } module_init(ftrace_demo_init); module_exit(ftrace_demo_exit);
我在下面使用一个脚本执行 Ftrace 的操作,自动追踪 HelloWorld 程序执行:
#!/bin/bash debugfs_path=/debug ftrace_call_path=$debugfs_path/tracing app_path=/home/dslab/test # 测试我们的 /debug 路径是否已经建立 if ! test -d $debugfs_path; then echo "I'll create the directory /debug" mkdir $debugfs_path else echo "Hum ,the /debug directory is standing by" fi # 测试debugfs是否已经挂载 mount | grep "debugfs" > /dev/null if [ $? != 0 ]; then echo "we have not mount debugfs" mount -t debugfs nodev $debugfs_path else echo "yeah,debugfs has been mounted" fi # 测试ftrace 是否可用 if ! test -d $ftrace_call_path; then echo "sorry, may be your kernel is not support for the ftrace" exit -1; else echo "Hum ,Ftrace is standing by" fi # 将目前的trace 文件清空 echo "" > $ftrace_call_path/trace # 选择 function_graph 跟踪器 echo "function_graph" > $ftrace_call_path/current_tracer # 我的Debian7 使用的3.2 内核上还有tracing_enabled ,先给它赋值 1 echo 1 > $ftrace_call_path/tracing_enabled # 使用 trace_pipe 将追踪结果重定向到/tmp/result(后台运行,使得下面的步骤得以进行) cat $ftrace_call_path/trace_pipe > /tmp/result & # 打开追踪 echo 1 > $ftrace_call_path/tracing_on # 我在这里执行了一个已经编译好helloworld 程序 exec $app_path/hello # 关闭追踪 echo 0 > $ftrace_call_path/tracing_on
dslab@wheezy:~$ sudo ./ftrace.sh [sudo] password for dslab: Hum ,the /debug directory is standing by yeah,debugfs has been mounted Hum ,Ftrace is standing by Hello World dslab@wheezy:~$
===================================
参考资料:
【1】Linux内核中的ftrace 文档,路径为:linux-source-3.2/Documentation/trace/ftrace.txt (还有个ftrace-design.txt也很值得学习)
【2】ftrace 简介 : http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace/
【3】使用 ftrace 调试 Linux 内核:
part1 : http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace1/
part2 : http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace2/
part3 : http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace3/