首页 > 其他分享 >tracer ftrace笔记(10)—— trace内容分析

tracer ftrace笔记(10)—— trace内容分析

时间:2022-10-11 17:14:53浏览次数:55  
标签:10 ftrace trace seq iter print 内容分析 event struct

基于Linux-5.10

一、trace打印格式

1. 在把 raw trace 数据格式化成用户可读的形式时,trace数据分成两部分:一部分是 common 信息,一部分是用户自定义的 trace 信息,这两部分分开格式化。

common信息: 这部分有系统根据当前是 “Normal format” 还是 “Latency trace format”,选择使用 trace_print_context() 或者是 trace_print_lat_context() 函数来进行格式化。

用户trace信息: 这部分根据 type 字段找到对应的 trace_event 结构,根据其 event->funcs->trace() 函数来进行格式化。遵循谁存储谁解析的原则,由 TRACE_EVENT 的 TP_printk 参数决定。

以 # cat /sys/kernel/tracing/trace 为例,

trace_create_file("trace", 0644, d_tracer, tr, &tracing_fops);

tracing_fops.read
    seq_read //读操作实际最后落在 tracer_seq_ops 的 s_next() 和 s_show() 上
        tracer_seq_ops.next
            s_next
                trace_find_next_entry_inc
                    __find_next_entry //取出下一个entry
                    trace_iterator_increment //增加iter中的读指针
        tracer_seq_ops.show
            s_show
                print_trace_line
                    print_trace_fmt
                        trace_print_context //打印每条trace的头部common信息

print_trace_fmt() 函数:

static enum print_line_t print_trace_fmt(struct trace_iterator *iter) //kernel/trace/trace.c
{
    struct trace_array *tr = iter->tr;
    struct trace_seq *s = &iter->seq;
    unsigned long sym_flags = (tr->trace_flags & TRACE_ITER_SYM_MASK);
    struct trace_entry *entry;
    struct trace_event *event;

    entry = iter->ent;

    test_cpu_buff_start(iter);

    event = ftrace_find_event(entry->type);

    /* 1. 打印头部common信息 */
    if (tr->trace_flags & TRACE_ITER_CONTEXT_INFO) {
        if (iter->iter_flags & TRACE_FILE_LAT_FMT)
            /* Latency trace format */
            trace_print_lat_context(iter);
        else
            /* Normal format */
            trace_print_context(iter);
    }

    if (trace_seq_has_overflowed(s))
        return TRACE_TYPE_PARTIAL_LINE;

    /* 2. 打印用户trace信息 */
    if (event)
        return event->funcs->trace(iter, sym_flags, event);

    trace_seq_printf(s, "Unknown type %d\n", entry->type);

    return trace_handle_return(s);
}

(1) 只看"Normal format"下头部信息的打印,打印comm、pid、tgid、cpu ts 信息:

int trace_print_context(struct trace_iterator *iter) //kernel/trace/trace_output.c
{
    struct trace_array *tr = iter->tr;
    struct trace_seq *s = &iter->seq;
    struct trace_entry *entry = iter->ent;
    unsigned long long t;
    unsigned long secs, usec_rem;
    char comm[TASK_COMM_LEN];

    /* 是从cmdline中找的task->comm信息 */
    trace_find_cmdline(entry->pid, comm);

    /* 打印trace记录时的 cur->comm 和 cur->pid */
    trace_seq_printf(s, "%16s-%-7d ", comm, entry->pid);

    if (tr->trace_flags & TRACE_ITER_RECORD_TGID) {
        unsigned int tgid = trace_find_tgid(entry->pid);

        if (!tgid)
            trace_seq_printf(s, "(-------) ");
        else
            /* 打印tgid */
            trace_seq_printf(s, "(%7d) ", tgid);
    }

    /* 打印trace抓取时所在的cpu */
    trace_seq_printf(s, "[%03d] ", iter->cpu);

    if (tr->trace_flags & TRACE_ITER_IRQ_INFO)
        /* 打印关中断关抢占状态 */
        trace_print_lat_fmt(s, entry);

    if (iter->iter_flags & TRACE_FILE_TIME_IN_NS) {
        t = ns2usecs(iter->ts);
        usec_rem = do_div(t, USEC_PER_SEC);
        secs = (unsigned long)t;
        /* 打印时间戳 */
        trace_seq_printf(s, " %5lu.%06lu: ", secs, usec_rem);
    } else
        trace_seq_printf(s, " %12llu: ", iter->ts);

    return !trace_seq_has_overflowed(s);
}

(2) struct trace_event 类型的 event->funcs->trace() 最后调用到的是 “include/trace/trace_event.h” 中的 trace_raw_output_##call() 函数。以 sched_blocked_reason 为例就是 trace_raw_output_sched_blocked_reason(),在它中打印用户自定义信息。

static notrace enum print_line_t trace_raw_output_sched_blocked_reason(struct trace_iterator *iter,
        int flags, struct trace_event *trace_event)
{
    /* iter->seq:为output buffer */
    struct trace_seq *s = &iter->seq;
    /*
     * iter->tmp_seq:为临时buffer,供 __get_bitmask()、__print_flags()、
     * __print_symbolic()等一系列函数先把值转换成字符串
     */
    struct trace_seq __maybe_unused *p = &iter->tmp_seq;
    /* 使用trace_event自定义的结构指向这片区域,来进行引用 */
    struct trace_event_raw_sched_blocked_reason *field;
    int ret;

    /* iter->ent:为ringbuffer原始数据的存放buffer */
    field = (typeof(field))iter->ent;
    /* 在output buffer的最前头,打印出trace_event的name */
    ret = trace_raw_output_prep(iter, trace_event);
    if (ret != TRACE_TYPE_HANDLED)
        return ret;
    /* 把ringbuffer中的原始数据根据格式打印到output buffer当中*/

    trace_seq_printf(s, "pid=%d iowait=%d caller=%pS" "\n", field->pid, field->io_wait, field->caller);

    return trace_handle_return(s);
}

trace_iterator 只是一个中间临时变量,主要是利用 iter->seq、iter->tmp_seq 把 iter->ent 指向的 ringbuffer 数据按照 format 转换成用户可读的数据。

用户部分除了可以看 TRACE_EVENT 的 TP_printk 参数外,还可以cat format 文件进行查看

/sys/kernel/tracing/events/sched/sched_blocked_reason # cat format
name: sched_blocked_reason
ID: 84
format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3;       size:1; signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;

        field:pid_t pid;        offset:8;       size:4; signed:1;
        field:void* caller;     offset:16;      size:8; signed:0;
        field:bool io_wait;     offset:24;      size:1; signed:0;

print fmt: "pid=%d iowait=%d caller=%pS", REC->pid, REC->io_wait, REC->caller

2. 打印格式举例:

crtc_commit:158 918-918     (    918) [002] d..2  2521.440658: sched_blocked_reason: pid=27443 iowait=0 caller=icc_set_tag+0x5c/0x1a4
               <idle>-0     (-------) [003] d.s3  2521.444053: sched_blocked_reason: pid=13 iowait=0 caller=rcu_gp_fqs_loop+0x154/0xac4
crtc_event:158 919-919      (    919) [000] d..5  2521.449214: sched_waking: comm=presentFence pid=2987 prio=98 target_cpu=000

 

 

 

 

 

 

参考:

深入理解Linux ftrace 之 trace event: https://mp.weixin.qq.com/s/1A02qv5SIEgTEvsN1DWzqQ

 

标签:10,ftrace,trace,seq,iter,print,内容分析,event,struct
From: https://www.cnblogs.com/hellokitty2/p/16779806.html

相关文章

  • tracer ftrace笔记(9)—— TRACE_EVENT 初始化
    基于Linux-5.10一、内核启动时遍历trace_event_call初始化流程1.TRACE_EVENT()多次展开定义了各种实现函数以后,最终把本event的所有的函数和数据存放在一个类型为s......
  • 英飞凌IPW65R110CFDA车规MOS,原厂渠道ASEMI代理
    编辑-ZIPW65R110CFDA英飞凌MOS管参数:型号:IPW65R110CFDA连续漏极电流(ID):99.6A功耗(Ptot):277.8W贮存温度和工作结温(Tstg,Tj):-40~150℃漏源击穿电压V(BR)DSS:650V栅极阈值电压V(GS)......
  • [2022.10.11 模拟赛] 联通块
    题意简述给定一颗树,每个点有点权\((a_i,b_i)\)。问满足\(\suma_i\lem\)的连通块的\(\sumb_i\)的最大值。\(n\le10^3,m\le10^4\)分析有一个显然的\(\mat......
  • 510约束_外键约束和511和约束_外键约束的级联操作
    外键约束外键约束:foreignkey,让表与表产生关系,从而保证数据的正确性1.在创建表时,可以添加外键语法:CREATETABLE表名(....(值)外键列CONSTRAINT外键名称,FOREIGNKEY(外......
  • PyPackage01---Pandas10_apply方法使用
    Intro  R里面apply族函数很强大,原来以为python的是阉割版,没想到也很强大,还是需要多看看文档。。。相关环境和package信息:importsysimportpandasaspdimportnumpyas......
  • Final Cut Pro for Mac(fcpx视频剪辑)v10.6.4中文直装版 永久使用
    FinalCutPro forMac是一款专业视频非线性编辑器,FinalCutPro拥有创新的视频编辑方式,强大的媒体整理功能,优化输出视频效果,并可编辑iPhone13及iPhone13Pro上以「......
  • CF1420D & gym102012 G
    CF1420D:注意到任意条线段的交集如果非空的话必定是一条线段,且这条线段的左端点一定是某条线段的左端点。很明显先将线段离散化,然后去枚举相交的线段的左端点。我们设\(......
  • 10.11
    A.relax小学数学题,前二十五分钟A了,有时间浪费的话就是读题慢。B.Permutation没有构造出来,用一个半小时想题+打了前五十分的表,打表也打得没有技术,完全人工计算。为什么......
  • CP2102
    CP2102是一种振荡器,具有集成度高的特点,可内置USB2.0全速功能控制器、USB收发器、晶体振荡器、EEPROM及异步串行数据总线(UART),支持调制解调器全功能信号,无需任何外部的USB器......
  • 10个Python脚本来自动化你的日常任务
    在这个自动化时代,我们有很多重复无聊的工作要做。想想这些你不再需要一次又一次地做的无聊的事情,让它自动化,让你的生活更轻松。那么在本文中,我将向您介绍10个Python自......