在trace_events.h中会使用#include来包含trace-events-sample.h 七次意味着会对其中的TRACE_EVENT(...)系列宏定义进行7次展开。每次展开起到的作用都是不一样的。在 trace_events.h中主要是处理参数空间的分配,参数格式化,以及一大推结构体的定义。
由于这个过程很漫长,对读者也是一个挑战,只有真正对tracepoint感兴趣的读者才会化时间和精力来进行宏定义的展开。所以我将直接将注释过的trace_events.h文件内容贴出来。
对trace/trace_events.h头文件注释/* SPDX-License-Identifier: GPL-2.0 */
/** Stage 1 of the trace events.** Override the macros in <trace/trace_events.h> to include the following:* 主要是将struct trace_event_raw_<call> 中的结构体进行展开* struct trace_event_raw_<call> {* struct trace_entry ent;* <type> <item>;* <type2> <item2>[<len>];* [...]* };** The <type> <item> is created by the __field(type, item) macro or* the __array(type2, item2, len) macro.* We simply do "type item;", and that will create the fields* in the structure.* 将结构体成员进行展开*//*包含 linux/trace_events.h头文件,一些重要的数据结构*/
#include <linux/trace_events.h>#ifndef TRACE_SYSTEM_VAR
/*如果没有定义TRACE_SYSTEM_VAR,则设置TRACE_SYSTEM_VAR值为TRACE_SYSTEM*/
#define TRACE_SYSTEM_VAR TRACE_SYSTEM
#endif/*__app的作用就是将宏参数展开后的结果进行字符串化,如果不是宏参数的话则对其进行字符串化*/
#define __app__(x, y) str__##x##y
#define __app(x, y) __app__(x, y) /*如果x,y为宏定义的话,会对其进行展开*//*展开后为:str_sample_trace__trace_system_name (TRACE_SYSTEM_VAR在trace-events-sample.h中定义)*/
#define TRACE_SYSTEM_STRING __app(TRACE_SYSTEM_VAR,__trace_system_name)#define TRACE_MAKE_SYSTEM_STR() \static const char TRACE_SYSTEM_STRING[] = /*保存到字符串中*/\__stringify(TRACE_SYSTEM) /*TRACE_SYSTEM值为sample-trace*//*定义全局字符串 str_sample_trace__trace_system_name[]= "sample-trace"*/
TRACE_MAKE_SYSTEM_STR();#undef TRACE_DEFINE_ENUM
/*ENUM:枚举*/
#define TRACE_DEFINE_ENUM(a) \static struct trace_eval_map __used __initdata \__##TRACE_SYSTEM##_##a = /*__sample_trace_##a*/ \{ \.system = TRACE_SYSTEM_STRING, \.eval_string = #a, /*字符串值*/ \.eval_value = a /*数值值*/ \}; \static struct trace_eval_map __used /*结构体指针*/\__attribute__((section("_ftrace_eval_map"))) \*TRACE_SYSTEM##_##a = &__##TRACE_SYSTEM##_##a /*指针指向字符串*/#undef TRACE_DEFINE_SIZEOF
/*SIZEOF:长度*/
#define TRACE_DEFINE_SIZEOF(a) \static struct trace_eval_map __used __initdata \__##TRACE_SYSTEM##_##a = /*__sample_trace_##a*/ \{ \.system = TRACE_SYSTEM_STRING, \.eval_string = "sizeof(" #a ")", /*注意是"sizeof(" #a ")" 字符串整体赋值给.eval_string*/\.eval_value = sizeof(a) /*长度值*/ \}; \static struct trace_eval_map __used \__attribute__((section("_ftrace_eval_map"))) \*TRACE_SYSTEM##_##a = &__##TRACE_SYSTEM##_##a/*TRACE_DEFINE_ENUMe和TRACE_DEFINE_SIZEOF的差别*/
/** DECLARE_EVENT_CLASS can be used to add a generic function* handlers for events. That is, if all events have the same* parameters and just have distinct(不同的) trace points.* Each tracepoint can be defined with DEFINE_EVENT and that* will map the DECLARE_EVENT_CLASS to the tracepoint.** TRACE_EVENT is a one to one mapping between tracepoint and template.*/
/*在tracepoint.h中定义DECLARE_EVENT_CLASS为空,定义DEFINE_EVENT调用DECLARE_TRACE,如下:#define DEFINE_EVENT(template, name, proto, args) \DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))在define_trace.h中定义DECLARE_TRACE为空,所以DEFINE_EVENT为空#define DECLARE_TRACE(name, proto, args)所以在当前代码行中,TRACE_EVENT宏定义为空,没有任何作用,但是紧接着会出现如下代码:#undef DECLARE_EVENT_CLASS#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \struct trace_event_raw_##name { \struct trace_entry ent; \tstruct \char __data[0]; \};static struct trace_event_class event_class_##name;重定义了DECLARE_EVENT_CLASS,所以本阶段的TRACE_EVENT就如下面定义一样不再为空,需要对其中的后续参数尤其是tstruct进行展开因为在trace_event.h文件中主要对TRACE_EVENT(...)中剩下的参数进行处理。
*/
#undef TRACE_EVENT
/*定义TRACE_EVENT避免trace-event-sample.h文件再次include时,被修改,因为trace-event-sample.h包含了tracepoint.h文件其会判断如果TRACE_EVENT未定义则会被定义,DECLARE_TRACE也是如此。
*/
#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \DECLARE_EVENT_CLASS(name, /*本阶段TRACE_EVENT演变为对tstruct的成员参数进行展开*/\PARAMS(proto), \PARAMS(args), \PARAMS(tstruct), \PARAMS(assign), \PARAMS(print)); \DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)); /*定义struct trace_event_call event_##name结构体*//*声明,定义变量*/
#undef __field
#define __field(type, item) type item;#undef __field_ext
#define __field_ext(type, item, filter_type) type item;#undef __field_struct
#define __field_struct(type, item) type item;#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type) type item;/*声明,定义数组*/
#undef __array
#define __array(type, item, len) type item[len];/*动态类型暂时不处理,注意其展开形式*/
#undef __dynamic_array
#define __dynamic_array(type, item, len) u32 __data_loc_##item; /*u32变量,type和len参数未使用*/#undef __string
#define __string(item, src) __dynamic_array(char, item, -1) /*u32 __data_loc_##item*/#undef __bitmask
#define __bitmask(item, nr_bits) __dynamic_array(char, item, -1) /*u32 __data_loc_##item**//*定义TP_STRUCT__entry*/
#undef TP_STRUCT__entry
#define TP_STRUCT__entry(args...) args/*DECLARE_EVENT_CLASS宏定义,其中的name为模板通用名称内部定义一个新的结构体struct trace_event_raw_##name以及声明全局结构体变量struct trace_event_class event_class_##name
*/
#undef DECLARE_EVENT_CLASS
/*struct trace_event_raw_##name结构体内部嵌入了tstruct,应该是为了便于管理TP_STRUCT__entry包裹的结构体*/
#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \struct trace_event_raw_##name { /*定义一个新的结构体,以模板名称结尾*/\struct trace_entry ent; \tstruct /*tstruct是一个用TP_STRUCT__entry包裹的结构体,需要使用__field,__array等宏对成员进行展开,当前阶段会对其进行展开*/\char __data[0]; /*__data为a占位符,开始存放动态数据的地址*/ \}; \\ /*声明全局结构体变量struct trace_event_class event_class_##name*/static struct trace_event_class event_class_##name;/*下面的DEFINE_xxx宏定义与DECLARE_EVENT_CLASS配合使用*/
/*声明全局结构体变量 static struct trace_event_call event_##name(四字节对齐)*/
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args) /*template,proto,args参数都未使用*/\static struct trace_event_call __used \__attribute__((__aligned__(4))) event_##name/*声明全局结构体变量 static struct trace_event_call event_##name(四字节对齐)*/
#undef DEFINE_EVENT_FN
#define DEFINE_EVENT_FN(template, name, proto, args, reg, unreg) \DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))/*声明全局结构体变量 static struct trace_event_call event_##name(四字节对齐)*/
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))/* Callbacks are meaningless to ftrace. */
/*TRACE_EVENT_FN在TRACE_EVENT的基础上多了reg和unreg参数用于enable和disable时调用
*/
#undef TRACE_EVENT_FN
#define TRACE_EVENT_FN(name, proto, args, tstruct, \assign, print, reg, unreg) \TRACE_EVENT(name, PARAMS(proto), PARAMS(args), \PARAMS(tstruct), PARAMS(assign), PARAMS(print)) \/*在define_trace.h中存在如下定义:#define TRACE_EVENT_CONDITION(name, proto, args, cond, tstruct, assign, print) \TRACE_EVENT(name, \PARAMS(proto), \PARAMS(args), \PARAMS(tstruct), \PARAMS(assign), \PARAMS(print))
*/
#undef TRACE_EVENT_FN_COND
#define TRACE_EVENT_FN_COND(name, proto, args, cond, tstruct, \assign, print, reg, unreg) \TRACE_EVENT_CONDITION(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \PARAMS(tstruct), PARAMS(assign), PARAMS(print)) \#undef TRACE_EVENT_FLAGS
#define TRACE_EVENT_FLAGS(name, value) \__TRACE_EVENT_FLAGS(name, value)#undef TRACE_EVENT_PERF_PERM
#define TRACE_EVENT_PERF_PERM(name, expr...) \__TRACE_EVENT_PERF_PERM(name, expr)/*再次包含头文件(trace-events-sample.h)对其中的宏定义重新展开,针对宏定义参数展开,并且将TP_STRUCT__entry()结构中的静态类型成员进行展开。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)/** Stage 2 of the trace events.** Include the following:* 将 struct trace_event_data_offsets_<call> 中动态类型进行展开* struct trace_event_data_offsets_<call> {* u32 <item1>;* u32 <item2>;* [...]* };** The __dynamic_array() macro will create each u32 <item>, this is* to keep the offset of each array from the beginning of the event.* The size of an array is also encoded, in the higher 16 bits of <item>.*/#undef TRACE_DEFINE_ENUM
#define TRACE_DEFINE_ENUM(a)#undef TRACE_DEFINE_SIZEOF
#define TRACE_DEFINE_SIZEOF(a)/*上面过程已经完成静态类型展开,这里将下面的__field和__array宏定义为空*/
#undef __field
#define __field(type, item)#undef __field_ext
#define __field_ext(type, item, filter_type)#undef __field_struct
#define __field_struct(type, item)#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type)#undef __array
#define __array(type, item, len)/*__dynamic_array重新展开,前面展开为u32 __data_loc_item,现在类型为u32 item,item为变量名称*/
#undef __dynamic_array
#define __dynamic_array(type, item, len) u32 item;#undef __string
#define __string(item, src) __dynamic_array(char, item, -1) /*u32 item;*/#undef __bitmask
#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1) /*u32 item;*//*DECLARE_EVENT_CLASS 宏定义内容修改定义结构体 struct trace_event_data_offsets_##call
*/
#undef DECLARE_EVENT_CLASS
/*定一个结构体struct trace_event_data_offsets_##call,内部嵌入了tstruct,用于管理TP_STRUCT__entry包裹的结构体的动态类型成员*/
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) /*name变了个名字为call*/\struct trace_event_data_offsets_##call { \tstruct; /*tstruct是一个用TP_STRUCT__entry包裹的结构体,静态类型(__field,__array)前面已经展开完成,现在需要使用__string,__bitmask等宏对动态成员进行展开*/\};/*DEFINE_EVENT宏定义为空*/
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))#undef TRACE_EVENT_FLAGS
#define TRACE_EVENT_FLAGS(event, flag)#undef TRACE_EVENT_PERF_PERM
#define TRACE_EVENT_PERF_PERM(event, expr...)/*再次包含头文件(trace-events-sample.h)对其中的宏定义重新展开,DECLARE_EVENT_CLASS宏定义发生修改需要重新展开,针对DECLARE_EVENT_CLASS宏定义,将TP_STRUCT__entry() 结构中的动态成员(string...)进行展开。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)/** Stage 3 of the trace events.** Override the macros in <trace/trace_events.h> to include the following:** enum print_line_t* trace_raw_output_<call>(struct trace_iterator *iter, int flags)* {* struct trace_seq *s = &iter->seq;在第一阶段定义* struct trace_event_raw_<call> *field; <-- defined in stage 1* struct trace_entry *entry;* struct trace_seq *p = &iter->tmp_seq;* int ret;** entry = iter->ent;** if (entry->type != event_<call>->event.type) {* WARN_ON_ONCE(1);* return TRACE_TYPE_UNHANDLED;* }** field = (typeof(field))entry;** trace_seq_init(p);* ret = trace_seq_printf(s, "%s: ", <call>);* if (ret)* ret = trace_seq_printf(s, <TP_printk> "\n");* if (!ret)* return TRACE_TYPE_PARTIAL_LINE;** return TRACE_TYPE_HANDLED;* }** This is the method used to print the raw event to the trace* output format. Note, this is not needed if the data is read* in binary.* 这是用于将原始事件内容输出到trace 缓冲区输出格式。* 注意,如果读取数据为二进制,则不需要这样做。*//*在TP_fast_assign中使用的都是__entry,这里将__entry定义为field, 因为后面的宏定义中指向结构体的指针为field*/
#undef __entry
#define __entry field#undef TP_printk
#define TP_printk(fmt, args...) fmt "\n", args#undef __get_dynamic_array
#define __get_dynamic_array(field) \((void *)__entry + (__entry->__data_loc_##field & 0xffff)) /*为什么要& 0xffff,动态数据内容开始地址*/#undef __get_dynamic_array_len
#define __get_dynamic_array_len(field) \((__entry->__data_loc_##field >> 16) & 0xffff) /*为什么要>>16位,看后面。动态数据内容空间总长度*/#undef __get_str
#define __get_str(field) ((char *)__get_dynamic_array(field))#undef __get_bitmask
#define __get_bitmask(field) \({ \void *__bitmask = __get_dynamic_array(field); \unsigned int __bitmask_size; \__bitmask_size = __get_dynamic_array_len(field); \trace_print_bitmask_seq(p, __bitmask, __bitmask_size); /*将数据写入trace_seqn缓存区*/\})#undef __print_flags
/*处理TP_printk中的__print_flags,__print_symbolic等符号*/
/*trace_print_flags_seq:flag_array[](__flags)中的每个成员的mask值包含在flags中则输出对应的name到trace_seq中,从flags中清除mask的值,继续判断flag_array[]中的下一个成员。
*/
#define __print_flags(flag, delim, flag_array...) \({ \static const struct trace_print_flags __flags[] = \{ flag_array, { -1, NULL }}; \trace_print_flags_seq(p, delim, flag, __flags); \})#undef __print_symbolic
/*trace_print_symbols_seq:将symbol_array[](symbols)中的成员的mask值等于val则输出对应的name到trace_seq中,然后就break跳出.只输出最先查找到的成员的name
*/
#define __print_symbolic(value, symbol_array...) \({ \static const struct trace_print_flags symbols[] = \{ symbol_array, { -1, NULL }}; \trace_print_symbols_seq(p, value, symbols); \})#undef __print_flags_u64
#undef __print_symbolic_u64
#if BITS_PER_LONG == 32
#define __print_flags_u64(flag, delim, flag_array...) \({ \static const struct trace_print_flags_u64 __flags[] = \{ flag_array, { -1, NULL } }; \trace_print_flags_seq_u64(p, delim, flag, __flags); \})#define __print_symbolic_u64(value, symbol_array...) \({ \static const struct trace_print_flags_u64 symbols[] = \{ symbol_array, { -1, NULL } }; \trace_print_symbols_seq_u64(p, value, symbols); \})
#else
#define __print_flags_u64(flag, delim, flag_array...) \__print_flags(flag, delim, flag_array)#define __print_symbolic_u64(value, symbol_array...) \__print_symbolic(value, symbol_array)
#endif#undef __print_hex
/*以%2.2x格式打印16进制数据*/
#define __print_hex(buf, buf_len) \trace_print_hex_seq(p, buf, buf_len, false)#undef __print_hex_str
#define __print_hex_str(buf, buf_len) \trace_print_hex_seq(p, buf, buf_len, true)#undef __print_array
/*数组成员元素大小必须为 1 2 4 8trace_print_array_seq:打印数组{a,b,c,d...}
*/
#define __print_array(array, count, el_size) \({ \BUILD_BUG_ON(el_size != 1 && el_size != 2 && \el_size != 4 && el_size != 8); \trace_print_array_seq(p, array, count, el_size); \})#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
static notrace enum print_line_t \
trace_raw_output_##call(struct trace_iterator *iter, int flags, \struct trace_event *trace_event) \
{ \struct trace_seq *s = &iter->seq; \struct trace_seq __maybe_unused *p = &iter->tmp_seq; \struct trace_event_raw_##call *field; \ /*注意field的类型,为struct trace_event_raw_##call,包含静态成员以及u32 __data_loc_item(动态成员)*/int ret; \\field = (typeof(field))iter->ent; \ /*struct trace_entry *ent;*/\ret = trace_raw_output_prep(iter, trace_event); \if (ret != TRACE_TYPE_HANDLED) \return ret; \\trace_seq_printf(s, print); \ /*输出print的内容到trace_seq*/\return trace_handle_return(s); \ /*判断是否溢出*/
} \
static struct trace_event_functions trace_event_type_funcs_##call = { \.trace = trace_raw_output_##call, \
};#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
static notrace enum print_line_t \
trace_raw_output_##call(struct trace_iterator *iter, int flags, \struct trace_event *event) \
{ \struct trace_event_raw_##template *field; \struct trace_entry *entry; \struct trace_seq *p = &iter->tmp_seq; \\entry = iter->ent; \\if (entry->type != event_##call.event.type) { \WARN_ON_ONCE(1); \return TRACE_TYPE_UNHANDLED; \} \\field = (typeof(field))entry; \\trace_seq_init(p); \return trace_output_call(iter, #call, print); \
} \
static struct trace_event_functions trace_event_type_funcs_##call = { \.trace = trace_raw_output_##call, \
};/*再次包含头文件(trace-events-sample.h)对其中的宏定义重新展开,主要是处理传入的TP_printk中的__print_symbolic,__print_flags,__print_array等内容。#include "./trace-events-sample.h"
*/#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)#undef __field_ext
/*trace_define_field在内核中为类型分配空间,设置name,type,offset,size*/
#define __field_ext(type, item, filter_type) \ret = trace_define_field(event_call, #type, #item, \offsetof(typeof(field), item), /*item在field内部的偏移*/\sizeof(field.item), \is_signed_type(type), filter_type); \if (ret) \return ret;#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type) \ret = trace_define_field(event_call, #type, #item, \offsetof(typeof(field), item), \sizeof(field.item), \0, filter_type); \if (ret) \return ret;/*__field被重新定义*/
#undef __field
#define __field(type, item) __field_ext(type, item, FILTER_OTHER)#undef __field_struct
#define __field_struct(type, item) __field_struct_ext(type, item, FILTER_OTHER)#undef __array
#define __array(type, item, len) \do { \char *type_str = #type"["__stringify(len)"]"; \BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \ret = trace_define_field(event_call, type_str, #item, \offsetof(typeof(field), item), \sizeof(field.item), \is_signed_type(type), FILTER_OTHER); \if (ret) \return ret; \} while (0);#undef __dynamic_array
#define __dynamic_array(type, item, len) \ret = trace_define_field(event_call, "__data_loc " #type "[]" /*数组类型*/, #item, \offsetof(typeof(field), __data_loc_##item), \sizeof(field.__data_loc_##item), /*sizeof(u32)*/ \is_signed_type(type), FILTER_OTHER);#undef __string
#define __string(item, src) __dynamic_array(char, item, -1)#undef __bitmask
#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
static int notrace __init \
trace_event_define_fields_##call(struct trace_event_call *event_call) \
{ \struct trace_event_raw_##call field; /*struct trace_event_raw_##call为前面定义的结构体 u32 __data_loc_##item*/ \int ret; \\tstruct; /*tstruct结构体,这里是被重新展开,分配数据空间struct ftrace_event_field管理内部数据 */ \\return ret; \
}/*定义DEFINE_EVENT为空*/
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))/*再次包含头文件(trace-events-sample.h)对其中的TP_STRUCT__entry宏定义重新展开,对其中的成员进行管理。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)/** remember the offset of each array from the beginning of the event.*/#undef __entry
#define __entry entry#undef __field
#define __field(type, item)#undef __field_ext
#define __field_ext(type, item, filter_type)#undef __field_struct
#define __field_struct(type, item)#undef __field_struct_ext
#define __field_struct_ext(type, item, filter_type)#undef __array
#define __array(type, item, len)#undef __dynamic_array
/*重定义__dynamic_array*/
#define __dynamic_array(type, item, len) \__item_length = (len) * sizeof(type); /*总长度*/\__data_offsets->item = __data_size + /*__data_offsets为指向struct trace_event_data_offsets_##call结构体的指针,__data_size为累加量*/\offsetof(typeof(*entry), __data); /*entry为指向struct trace_event_raw_##call结构体的指针,__data为该结构体的成员 char __data[0];,为占位符,表示存放动态数据内容开始地址*/\__data_offsets->item |= __item_length << 16; /*高16位存放总长度*/ \__data_size += __item_length;#undef __string
/*重定义__string,__dynamic_array内部会处理src的长度问题*/
#define __string(item, src) __dynamic_array(char, item, \strlen((src) ? (const char *)(src) : "(null)"/*src为空时设置为(null)*/) + 1) /*strlen(src)+1*//** __bitmask_size_in_bytes_raw is the number of bytes needed to hold* num_possible_cpus().*/
/*bit向上取字节个数*/
#define __bitmask_size_in_bytes_raw(nr_bits) \(((nr_bits) + 7) / 8)/*bit向上取long个数*/
#define __bitmask_size_in_longs(nr_bits) \((__bitmask_size_in_bytes_raw(nr_bits) + \((BITS_PER_LONG / 8) - 1)) / (BITS_PER_LONG / 8))/** __bitmask_size_in_bytes is the number of bytes needed to hold* num_possible_cpus() padded out to the nearest long. This is what* is saved in the buffer, just to be consistent.*/
/*bit向上取字节个数*/
#define __bitmask_size_in_bytes(nr_bits) \(__bitmask_size_in_longs(nr_bits) * (BITS_PER_LONG / 8))#undef __bitmask
#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, \__bitmask_size_in_longs(nr_bits))#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
static inline notrace int trace_event_get_offsets_##call( \struct trace_event_data_offsets_##call *__data_offsets, proto) /*struct trace_event_data_offsets_##call为前面定义的结构体 u32 item*/\
{ \int __data_size = 0; /*__data_size的定义,初始值为0*/ \int __maybe_unused __item_length; \struct trace_event_raw_##call __maybe_unused *entry; /*注意entry的类型为struct trace_event_raw_##call,前面定义*/\\tstruct; /*tstruct结构体,这里是被重新展开,动态类型进行处理,按照展开处理,所有动态类型数据集中存放到一起*/\\return __data_size; /*__data_size统计tstruct中动态类型数据的总空间大小*/ \
}/*定义DEFINE_EVENT为空*/
#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args)#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))/*再次包含头文件(trace-events-sample.h)对其中的宏定义重新展开。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)/** Stage 4 of the trace events.** Override the macros in <trace/trace_events.h> to include the following:** For those macros defined with TRACE_EVENT:** static struct trace_event_call event_<call>;** static void trace_event_raw_event_<call>(void *__data, proto)* {* struct trace_event_file *trace_file = __data;* struct trace_event_call *event_call = trace_file->event_call;* struct trace_event_data_offsets_<call> __maybe_unused __data_offsets;* unsigned long eflags = trace_file->flags;* enum event_trigger_type __tt = ETT_NONE;* struct ring_buffer_event *event;* struct trace_event_raw_<call> *entry; <-- defined in stage 1* struct ring_buffer *buffer;* unsigned long irq_flags;* int __data_size;* int pc;** if (!(eflags & EVENT_FILE_FL_TRIGGER_COND)) {* if (eflags & EVENT_FILE_FL_TRIGGER_MODE)* event_triggers_call(trace_file, NULL);* if (eflags & EVENT_FILE_FL_SOFT_DISABLED)* return;* }** local_save_flags(irq_flags);* pc = preempt_count();** __data_size = trace_event_get_offsets_<call>(&__data_offsets, args);** event = trace_event_buffer_lock_reserve(&buffer, trace_file,* event_<call>->event.type,* sizeof(*entry) + __data_size,* irq_flags, pc);* if (!event)* return;* entry = ring_buffer_event_data(event);** { <assign>; } <-- Here we assign the entries by the __field and* __array macros.** if (eflags & EVENT_FILE_FL_TRIGGER_COND)* __tt = event_triggers_call(trace_file, entry);** if (test_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT,* &trace_file->flags))* ring_buffer_discard_commit(buffer, event);* else if (!filter_check_discard(trace_file, entry, buffer, event))* trace_buffer_unlock_commit(buffer, event, irq_flags, pc);** if (__tt)* event_triggers_post_call(trace_file, __tt);* }** static struct trace_event ftrace_event_type_<call> = {* .trace = trace_raw_output_<call>, <-- stage 2* };** static char print_fmt_<call>[] = <TP_printk>;** static struct trace_event_class __used event_class_<template> = {* .system = "<system>",* .define_fields = trace_event_define_fields_<call>,* .fields = LIST_HEAD_INIT(event_class_##call.fields),* .raw_init = trace_event_raw_init,* .probe = trace_event_raw_event_##call,* .reg = trace_event_reg,* };** static struct trace_event_call event_<call> = {* .class = event_class_<template>,* {* .tp = &__tracepoint_<call>,* },* .event = &ftrace_event_type_<call>,* .print_fmt = print_fmt_<call>,* .flags = TRACE_EVENT_FL_TRACEPOINT,* };* // its only safe to use pointers when doing linker tricks to* // create an array.* static struct trace_event_call __used* __attribute__((section("_ftrace_events"))) *__event_<call> = &event_<call>;**/#ifdef CONFIG_PERF_EVENTS#define _TRACE_PERF_PROTO(call, proto) \static notrace void \perf_trace_##call(void *__data, proto);#define _TRACE_PERF_INIT(call) \.perf_probe = perf_trace_##call,#else
#define _TRACE_PERF_PROTO(call, proto)
#define _TRACE_PERF_INIT(call)
#endif /* CONFIG_PERF_EVENTS */#undef __entry
/*定义__entry为entry,因为定义entry的类型为struct trace_event_raw_##call*/
#define __entry entry#undef __field
#define __field(type, item)#undef __field_struct
#define __field_struct(type, item)#undef __array
#define __array(type, item, len)#undef __dynamic_array
#define __dynamic_array(type, item, len) \__entry->__data_loc_##item = __data_offsets.item; /*设置struct trace_event_raw_##call的成员__data_loc_##item的值,__data_offsets类型为struct trace_event_data_offsets_##call*/#undef __string
#define __string(item, src) __dynamic_array(char, item, -1) /*设置len为-1,意义不大,因为本阶段只处理赋值*/#undef __assign_str
#define __assign_str(dst, src) \strcpy(__get_str(dst), (src) ? (const char *)(src) : "(null)");#undef __bitmask
#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)#undef __get_bitmask
#define __get_bitmask(field) (char *)__get_dynamic_array(field)#undef __assign_bitmask
#define __assign_bitmask(dst, src, nr_bits) \memcpy(__get_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits)) /*注意,动态类型的空间还没分配*/#undef TP_fast_assign
/*开始处理TP_fast_assign的内容,开始赋值处理*/
#define TP_fast_assign(args...) args#undef __perf_count
#define __perf_count(c) (c)#undef __perf_task
#define __perf_task(t) (t)#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \\
static notrace void \
trace_event_raw_event_##call(void *__data, proto) \
{ \struct trace_event_file *trace_file = __data; \struct trace_event_data_offsets_##call __maybe_unused __data_offsets; /*__data_offsets出现了*/\struct trace_event_buffer fbuffer; \struct trace_event_raw_##call *entry; /*entry出现了*/ \int __data_size; \\if (trace_trigger_soft_disabled(trace_file)) \return; \\__data_size = trace_event_get_offsets_##call(&__data_offsets, args); /*返回tstruct 动态类型数据占用总空间大小*/\\entry = trace_event_buffer_reserve(&fbuffer, trace_file, /*核心作用是为即将记录的追踪事件预留一段连续的内存空间,确保事件数据的高效写入和完整性*/\sizeof(*entry) + __data_size); /*此时entry中的动态类型数据区存在内存空间了*/\\if (!entry) \return; \\tstruct /*处理tstruct*/\\{ assign; } /*处理TP_fast_assign*/\\trace_event_buffer_commit(&fbuffer); \
}
/** The ftrace_test_probe is compiled out, it is only here as a build time check* to make sure that if the tracepoint handling changes, the ftrace probe will* fail to compile unless it too is updated.*/#undef DEFINE_EVENT
#define DEFINE_EVENT(template, call, proto, args) \
static inline void ftrace_test_probe_##call(void) \
{ \check_trace_callback_type_##call(trace_event_raw_event_##template); \
}#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print)/*再次包含头文件(trace-events-sample.h)对其中的宏定义重新展开。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)#undef __entry
/*__entry重定义为REC*/
#define __entry REC#undef __print_flags
#undef __print_symbolic
#undef __print_hex
#undef __print_hex_str
#undef __get_dynamic_array
#undef __get_dynamic_array_len
#undef __get_str
#undef __get_bitmask
#undef __print_array#undef TP_printk
/*处理 TP_printk*/
#define TP_printk(fmt, args...) "\"" fmt "\", " __stringify(args)#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
_TRACE_PERF_PROTO(call, PARAMS(proto)); \
static char print_fmt_##call[] = print; \
static struct trace_event_class __used __refdata event_class_##call = { /*struct trace_event_class 结构体变量*/\.system = TRACE_SYSTEM_STRING, \.define_fields = trace_event_define_fields_##call, \.fields = LIST_HEAD_INIT(event_class_##call.fields),\.raw_init = trace_event_raw_init, \.probe = trace_event_raw_event_##call, \.reg = trace_event_reg, \_TRACE_PERF_INIT(call) \
};#undef DEFINE_EVENT
#define DEFINE_EVENT(template, call, proto, args) \\
static struct trace_event_call __used event_##call = { /*struct trace_event_call 结构体变量*/ \.class = &event_class_##template, \{ \.tp = &__tracepoint_##call, \}, \.event.funcs = &trace_event_type_funcs_##template, \.print_fmt = print_fmt_##template, \.flags = TRACE_EVENT_FL_TRACEPOINT, \
}; \
static struct trace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \\
static char print_fmt_##call[] = print; \\
static struct trace_event_call __used event_##call = { \.class = &event_class_##template, \{ \.tp = &__tracepoint_##call, \}, \.event.funcs = &trace_event_type_funcs_##call, \.print_fmt = print_fmt_##call, \.flags = TRACE_EVENT_FL_TRACEPOINT, \
}; \
static struct trace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call/*最后包含头文件(trace-events-sample.h)对其中的宏定义重新展开。#include "./trace-events-sample.h"
*/
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)