ftrace和perf

 

今天没去参加吃喝玩乐,跑去加班,不过心情还是愉悦的,因为有收获。真是利器啊。

调试例子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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值