Updated(2012/04/23):
刚看了elc2012的一篇关于使用ftrace调试性能问题的文章,也很不错
https://events.linuxfoundation.org/images/stories/pdf/lf_elc12_kobayashi.pdf
同时, 推荐下面这篇关于在ARM体系结构下使用Ftrace的文章
http://elinux.org/Ftrace_Function_Graph_ARM
以上支持ARM 的Ftrace的patch在commit:376cfa8730c08c0394d0aa1d4a80fd8c9971f323 中引入了kernel的mainline.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ftrace是用来帮助调试kernel,了解kernel中的运行机制及performance相关问题而设计的基于debugfs的kernel内部的trace机制.
Ftrace的一些前提知识:
搭建Ftrace调试环境
下面是如何使用ftrace
function_graph function nop ...
[tracing]# echo [function] > current_tracer -> 这里[]中键入目前支持的ftrace方式 [tracing]# cat current_tracer
把trace_printk("read foo %d out of bar %p\n", bar->foo, bar);加入一个模块 然后就可以通过读取cat /sys/kernel/debug/ftrace/trace 来查看相关log
[tracing]# echo 0 > tracing_on [tracing]# echo function_graph > current_tracer [tracing]# echo 1 > tracing_on; run_test; echo 0 > tracing_on
参照<Debug the kernel using Ftrace - part2>, 给了一个完整的例子, 如何在开发中使用这个接口[tracing]# echo nop > current_tracer[tracing]# echo test > trace_marker[tracing]# cat trace# tracer: nop## TASK-PID CPU# TIMESTAMP FUNCTION# | | | | | sh-848 [000] 1986.459489: tracing_mark_write:test
int trace_fd = -1; int marker_fd = -1; int main(int argc, char *argv) { char *debugfs; char path[256]; [...] debugfs = find_debugfs(); if (debugfs) { strcpy(path, debugfs); strcat(path,"/tracing/tracing_on"); trace_fd = open(path, O_WRONLY); if (trace_fd >= 0) write(trace_fd, "1", 1); strcpy(path, debugfs); strcat(path,"/tracing/trace_marker"); marker_fd = open(path, O_WRONLY);在一些critical section
if (marker_fd >= 0) write(marker_fd, "In critical area\n", 17); if (critical_function() < 0) { /* we failed! */ if (trace_fd >= 0) write(trace_fd, "0", 1); }其中find_debugfs()的代码是
#define MAX_PATH 256 #define _STR(x) #x #define STR(x) _STR(x) static const char *find_debugfs(void) { static char debugfs[MAX_PATH+1]; static int debugfs_found; char type[100]; FILE *fp; if (debugfs_found) return debugfs; if ((fp = fopen("/proc/mounts","r")) == NULL) return NULL; while (fscanf(fp, "%*s %" STR(MAX_PATH) "s %99s %*s %*d %*d\n", debugfs, type) == 2) { if (strcmp(type, "debugfs") == 0) break; } fclose(fp); if (strcmp(type, "debugfs") != 0) return NULL; debugfs_found = 1; return debugfs; }
[tracing]# echo xx > buffer_size_kb
cat stack_max_size
关于使用Ftrace的例子及一些ftrace结果的format,参见ftrace.txt
参考资料:
http://bec-systems.com/site/865/linux-tracing-tutorial
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=tree;f=Documentation/trace
http://lwn.net/Articles/322666/
http://lwn.net/Articles/365835/
http://lwn.net/Articles/366796/
http://lwn.net/Articles/370423/
http://elinux.org/Kernel_Trace_Systems