今天没去参加吃喝玩乐,跑去加班,不过心情还是愉悦的,因为有收获。真是利器啊。
调试例子ftrace_demo.c
/* * ftrace_demo.c */ #include #include #include MODULE_LICENSE("GPL"); static int ftrace_demo_init(void) { trace_printk("Can not see this in trace unless loaded for the second time\n"); tracing_off(); return 0; } static void ftrace_demo_exit(void) { trace_printk("Module unloading\n"); tracing_off(); } module_init(ftrace_demo_init); module_exit(ftrace_demo_exit);
Makefile
obj-m += ftrace_demo.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
ubuntu 10.10的内核里已经打开ftrace,看看/sys/kernel/debug/tracing/ 下的README,这就是使用方法。
tracing mini-HOWTO: # mount -t debugfs nodev /sys/kernel/debug # cat /sys/kernel/debug/tracing/available_tracers wakeup preemptirqsoff preemptoff irqsoff function sched_switch nop # cat /sys/kernel/debug/tracing/current_tracer nop # echo sched_switch > /sys/kernel/debug/tracing/current_tracer # cat /sys/kernel/debug/tracing/current_tracer sched_switch # cat /sys/kernel/debug/tracing/trace_options noprint-parent nosym-offset nosym-addr noverbose # echo print-parent > /sys/kernel/debug/tracing/trace_options # echo 1 > /sys/kernel/debug/tracing/tracing_enabled # cat /sys/kernel/debug/tracing/trace > /tmp/trace.txt # echo 0 > /sys/kernel/debug/tracing/tracing_enabled
巧妙的应用了gcc 的-pg选项,重载mcount,实现tracing的功能。据yakui说,这个只适用于kernel space,于是有了[4],于是调试user space也方便了。
之后是如何在要跟踪的代码中插入断点,参考[5]中的tracepoints.txt. 有几个commit可以参考。
kernel 中的 99ee7fac189893c90145a22b86bbcfdc98f69a9c 和 9d34e5db07303c9609053e2e651aa6d1fc74e923。 第二个,还没看明白。
折腾的功夫没到家啊。
继续前面的学习,并补充。
编译kernel,使之支持ftrace,需要打开如下选项
CONFIG_FUNCTION_TRACER CONFIG_FUNCTION_GRAPH_TRACER CONFIG_STACK_TRACER CONFIG_DYNAMIC_FTRACE
[7]中的代码,分析如下
TRACE_EVENT(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next), TP_ARGS(rq, prev, next), TP_STRUCT__entry( __array( char, prev_comm, TASK_COMM_LEN ) __field( pid_t, prev_pid ) __field( int, prev_prio ) __field( long, prev_state ) __array( char, next_comm, TASK_COMM_LEN ) __field( pid_t, next_pid ) __field( int, next_prio ) ), TP_fast_assign( memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN); __entry->prev_pid = prev->pid; __entry->prev_prio = prev->prio; __entry->prev_state = prev->state; memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); __entry->next_pid = next->pid; __entry->next_prio = next->prio; ), TP_printk("prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d", __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, __entry->prev_state ? __print_flags(__entry->prev_state, "|", { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, { 16, "Z" }, { 32, "X" }, { 64, "x" }, { 128, "W" }) : "R", __entry->next_comm, __entry->next_pid, __entry->next_prio) );
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
DECLARE_EVENT_CLASS(name, \
PARAMS(proto), \
PARAMS(args), \
PARAMS(tstruct), \
PARAMS(assign), \
PARAMS(print)); \
DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args));
kernel里的宏,翻起来太累了,看了include/trace/ftrace.h,彻底晕菜。还是让gcc来帮忙吧。radeon驱动里的例子,非常适合借鉴
gcc -E radeon_trace_points.c -I/work/linux-2.6/include -I/work/linux-2.6/include/drm -I/work/linux-2.6/arch/x86/include -I. -DCONFIG_TRACEPOINTS
只看
TRACE_EVENT(radeon_bo_create, TP_PROTO(struct radeon_bo *bo), TP_ARGS(bo), TP_STRUCT__entry( __field(struct radeon_bo *, bo) __field(u32, pages) ), TP_fast_assign( __entry->bo = bo; __entry->pages = bo->tbo.num_pages; ), TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages) );
static const char __tpstrtab_radeon_bo_create[] __attribute__((section("__tracepoints_strings"))) = "radeon_bo_create"; struct tracepoint __tracepoint_radeon_bo_create __attribute__((section("__tracepoints"))) = { __tpstrtab_radeon_bo_create, 0, ((void *)0), ((void *)0), ((void *)0) }; static struct tracepoint * const __tracepoint_ptr_radeon_bo_create __used __attribute__((section("__tracepoints_ptrs"))) = __tracepoint_radeon_bo_create;;;
1. ftrace简介
http://www.ibm.com/developerworks/cn/linux/l-cn-ftrace/index.html
2. 使用 ftrace 调试 Linux 内核
http://linux.cn/home/space-2-do-blog-id-326.html
http://linux.cn/home/space-2-do-blog-id-329.html
http://linux.cn/home/space-2-do-blog-id-331.html
3. Perf — Linux下的系统性能调优工具介绍http://blog.youkuaiyun.com/bluebeach/archive/2010/09/28/5912062.aspx
4. trace: Add user-space event tracing/injection
http://marc.info/?l=linux-kernel&m=128999569714133&w=2
5.第一手资料在kernel目录中 Documentation/trace/*
6. TRACE_EVENT()
http://lwn.net/Articles/379903/
7. sched_switch TRACE_EVENT definition
http://lwn.net/Articles/379903/
http://lwn.net/Articles/381064/
http://lwn.net/Articles/383362/