当前位置: 首页 > news >正文

linux tracepoint系列宏定义(TRACE_EVENT,DEFINE_TRACE等)展开过程分析之三 define_trace.h头文件

        在linux tracepoint系列宏定义(TRACE_EVENT,DEFINE_TRACE等)展开过程分析之二 文章中,我们知道trace-events-sample.h 文件在包含了tracepoint.h后第一次对TRACE_EVENT(...)等系列宏定义进行了展开,主要是构建tracepoint 调用钩子函数,注册/注销函数。展开的第二阶段,则是包含了define_trace.h头文件,那么在本阶段这些宏定义又会进行怎样的展开呢?

1、包含define_trace.h头文件

        在trace-events-sample.h文件的结尾使用#include <trace/define_trace.h> 包含了define_trace.h有文件,意味着在

预编译阶段该头文件会在此位置进行展开。

/*

* TRACE_INCLUDE_FILE is not needed if the filename and TRACE_SYSTEM are equal

*/

#define TRACE_INCLUDE_FILE trace-events-sample

/*

包含define_trace.h头文件,里面对TRACE_EVENT,TRACE_EVENT_CONDITION等宏进行重定义

那么包含trace-events-sample.hwn头文件的文件中后续使用的TRACE_EVENT,TRACE_EVENT_CONDITION等宏定义则来自define_trace.h文件

*/

#include <trace/define_trace.h>

        而在define_trace.h中会去包含包含trace-events-sample.h文件。因为define_trace.h中对TRACE_EVENT(...)等系列宏定义进行了#unset 后又#define 重新定义,所以包含trace-events-sample.h后,其中的TRACE_EVENT系列宏定义会被重新展开,本阶段的展开主要TRACE_EVENT调用DEFINE_TRACE定义并初始化struct tracepoint __tracepoint_##name变量

/* #include "./trace-events-sample.h" */
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

2、define_trace.h 头文件注释:

        注意:define_trace.h头文件在每个定义tracepoint的.h头文件中只有第一次的包含是有效的,因为 #undef CREATE_TRACE_POINTS会使define_trace.h再出进入时无效,除非明确定义CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS才有效。这个很重要,否则会给后面的理解造成困惑。

        下面张贴出对define_trace.h头文件的详细注释:

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Trace files that want to automate creation of all tracepoints defined
 * in their file should include this file. The following are macros that the
 * trace file may define:
 *
 * TRACE_SYSTEM defines the system the tracepoint is for
 *
 * TRACE_INCLUDE_FILE if the file name is something other than TRACE_SYSTEM.h
 *     This macro may be defined to tell define_trace.h what file to include.
 *     Note, leave off the ".h".
 *
 * TRACE_INCLUDE_PATH if the path is something other than core kernel include/trace
 *     then this macro can define the path to use. Note, the path is relative to
 *     define_trace.h, not the file including it. Full path names for out of tree
 *     modules must be used.
 */
/*在子系统tracepoint所在的.c文件中定义(trace-events-sample.c)*/
#ifdef CREATE_TRACE_POINTS

/* Prevent recursion */
/*意味着define_trace.h文件只能进入一次,因为这里使用#undefa取消其定义,后面就无法再次进入*/
#undef CREATE_TRACE_POINTS

#include <linux/stringify.h>

/*在该阶段,TRACE_EVENT系列宏定义重定义为DEFINE_TRACE系列宏,用于定义并初始化struct tracepoint __tracepoint_##name变量*/
#undef TRACE_EVENT /*取消之前的TRACE_EVENT定义*/
#define TRACE_EVENT(name, proto, args, tstruct, assign, print)	\
	DEFINE_TRACE(name) /*DEFINE_TRACE在tracepoint.h中定义,内部调用DEFINE_TRACE_FN*/

#undef TRACE_EVENT_CONDITION
#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
#define TRACE_EVENT_FN(name, proto, args, tstruct,		\
		assign, print, reg, unreg)			\
	DEFINE_TRACE_FN(name, reg, unreg)

#undef TRACE_EVENT_FN_COND
#define TRACE_EVENT_FN_COND(name, proto, args, cond, tstruct,		\
		assign, print, reg, unreg)			\
	DEFINE_TRACE_FN(name, reg, unreg)

#undef DEFINE_EVENT
#define DEFINE_EVENT(template, name, proto, args) \
	DEFINE_TRACE(name)

#undef DEFINE_EVENT_FN
#define DEFINE_EVENT_FN(template, name, proto, args, reg, unreg) \
	DEFINE_TRACE_FN(name, reg, unreg)

#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
	DEFINE_TRACE(name)

#undef DEFINE_EVENT_CONDITION
#define DEFINE_EVENT_CONDITION(template, name, proto, args, cond) \
	DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args))

#undef DECLARE_TRACE 	/*在该阶段DECLARE_TRACE重定义为DEFINE_TRACE*/
#define DECLARE_TRACE(name, proto, args)	\
	DEFINE_TRACE(name)

#undef TRACE_INCLUDE
#undef __TRACE_INCLUDE

/*在定义TRACE_EVNET所在的.h头文件中已定义TRACE_INCLUDE_FILE为trace-events-sample(trace-events-sample.h)*/
#ifndef TRACE_INCLUDE_FILE
/*如果没有定义TRACE_INCLUDE_FILE,就设置其值为TRACE_SYSTEM*/
# define TRACE_INCLUDE_FILE TRACE_SYSTEM
# define UNDEF_TRACE_INCLUDE_FILE
#endif

/*在定义TRACE_EVNET所在的.h头文件中已定义TRACE_INCLUDE_PATH为 . (trace-events-sample.h)*/
#ifndef TRACE_INCLUDE_PATH
# define __TRACE_INCLUDE(system) <trace/events/system.h>
# define UNDEF_TRACE_INCLUDE_PATH
#else
		/*./trace-events-sample.h*/
# define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
#endif
/*TRACE_INCLUDE宏用于包含 trace-events-sample.h文件*/
# define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)

/* Let the trace headers be reread */
#define TRACE_HEADER_MULTI_READ

/*
	由于上面修改了大量关键宏定义,如TRACE_EVENT由之前tracepoint.h中的调用DECLARE_TRACE来声明实现tracepoint的注册/注销函数,钩子函数调用接口的功能
	修改为在该阶段TRACE_EVENT调用DEFINE_TRACE定义并初始化struct tracepoint __tracepoint_##name变量。
	所以需要再次包含头文件(trace-events-sample.h)对其中的宏定义重性进行展开,当然定义的作用也不相同。
	#include "./trace-events-sample.h"
*/
/* #include "./trace-events-sample.h" */
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

/* Make all open coded DECLARE_TRACE nops */

/*
	取消DECLARE_TRACE的定义,定义为空,因为在前面两个阶段已经完成了声明实现tracepoint的注册/注销函数,钩子函数调用接口
	以及义并初始化struct tracepoint __tracepoint_##name变量。
	因为在tracepoint.h中会判断DECLARE_TRACE是否定义,如果未定义则会重新定义,为了避免再次定义,所以这里设置为空。
*/
#undef DECLARE_TRACE
/*注意,DECLARE_TRACE设置为空*/
#define DECLARE_TRACE(name, proto, args) /*空*/

#ifdef TRACEPOINTS_ENABLED
/*包含trace/trace_events.h头文件,在trace_events.h头文件中会多次包含trace-events-sample.h,并对其进行多次展开*/
#include <trace/trace_events.h>
/*包含trace/perf.h头文件*/
#include <trace/perf.h>
#endif

/*取消下面的宏定义*/
#undef TRACE_EVENT
#undef TRACE_EVENT_FN
#undef TRACE_EVENT_FN_COND
#undef TRACE_EVENT_CONDITION
#undef DECLARE_EVENT_CLASS
#undef DEFINE_EVENT
#undef DEFINE_EVENT_FN
#undef DEFINE_EVENT_PRINT
#undef DEFINE_EVENT_CONDITION
#undef TRACE_HEADER_MULTI_READ
#undef DECLARE_TRACE

/* Only undef what we defined in this file */
#ifdef UNDEF_TRACE_INCLUDE_FILE
# undef TRACE_INCLUDE_FILE
# undef UNDEF_TRACE_INCLUDE_FILE
#endif

#ifdef UNDEF_TRACE_INCLUDE_PATH
# undef TRACE_INCLUDE_PATH
# undef UNDEF_TRACE_INCLUDE_PATH
#endif

/* We may be processing more files */
#define CREATE_TRACE_POINTS

#endif /* CREATE_TRACE_POINTS */

3、define_trace.h文件中包含trace-events-sample.h后,TRACE_EVENT的展开

以trace-events-sample.h中的TRACE_EVENT为例,说明其在本阶段的展开

TRACE_EVENT(foo_bar,
	/*trace_foo_bar函数原型*/
	TP_PROTO(const char *foo, int bar, const int *lst,
		 const char *string, const struct cpumask *mask),
 
	/*trace_foo_bar参数列表*/
	TP_ARGS(foo, bar, lst, string, mask),
 
	TP_STRUCT__entry(
		__array(	char,	foo,    10		) /*char foo[10]*/
		__field(	int,	bar			)		/*int bar*/
		__dynamic_array(int,	list,   __length_of(lst)) /*int list[]*/
		__string(	str,	string			)	/*str的值为string的内容*/
		__bitmask(	cpus,	num_possible_cpus()	)
	),
 
	/*如何给上述变量赋值*/
	TP_fast_assign(
		strlcpy(__entry->foo, foo, 10);
		__entry->bar	= bar;
		/*__get_dynamic_array获取list的起始地址*/
		memcpy(__get_dynamic_array(list), lst,
		       __length_of(lst) * sizeof(int));
		__assign_str(str, string);
		__assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus());
	),
 
	TP_printk("foo %s %d %s %s %s %s (%s)", __entry->foo, __entry->bar,
 

		  __print_flags(__entry->bar, "|",
				{ 1, "BIT1" },
				{ 2, "BIT2" },
				{ 4, "BIT3" },
				{ 8, "BIT4" }
			  ),

		  __print_array(__get_dynamic_array(list),
				__get_dynamic_array_len(list) / sizeof(int),
				sizeof(int)),
		  __get_str(str), __get_bitmask(cpus))
);

 展开后的内容如下:

TRACE_EVENTfoo_bar,宏开始展开,本阶段TRACE_EVENT主要用于 struct tracepoint __tracepoint_##name 结构体定义
static const char __tpstrtab_foo_bar[] __attribute__((section("__tracepoints_strings"))) = "foo_bar"; 
struct tracepoint __tracepoint_foo_bar __attribute__((section("__tracepoints"))) = { __tpstrtab_foo_bar, { .enabled = { 0 }, { .entries = (void *)0UL } }, ((void *)0), ((void *)0), ((void *)0) }; 
static struct tracepoint * const __tracepoint_ptr_foo_bar __attribute__((__used__)) __attribute__((section("__tracepoints_ptrs"))) = &__tracepoint_foo_bar;;

4、在define_trace.h中包含trace_events.h头文件

 如下:

/*包含trace/trace_events.h头文件,在trace_events.h头文件中会多次包含trace-events-sample.h,并对其进行多次展开*/
#include <trace/trace_events.h>

在trace_events.h头文件中,会再次使用老套路#unset和#define来重定义TRACE_EVENT(...)等一系列宏定义后再包含trace-events-sample.h,这样trace-events-sample.h中的宏定义又被再次展开为不同的内容。其实在trace_events.h中会使用#include来包含trace-events-sample.h 七次且每次的展开对应的目的都是不一样的。所以对trace_events.h的分析将是一个体力活儿和脑力活儿。

相关文章:

  • 【blender小技巧】Blender导出带贴图的FBX模型,并在unity中提取材质模型使用
  • telepresence使用指南
  • 【LH-开发记录】
  • Dockerfile 学习指南和简单实战
  • 一文介绍关于多模态的基础知识 !!
  • PHP弱类型hash比较缺陷
  • 高速连接器设计的技术挑战和解决方案
  • Dify智能体平台源码二次开发笔记(5) - 多租户的SAAS版实现(2)
  • 添加登录和注册功能
  • 图像预处理(OpenCV)-part2
  • 3.6 函数图像描绘
  • 3.6 集合
  • SpringBoot Starter自定义:创建可复用的自动配置模块
  • 基于QtC++音乐播放器whisper语音转文字歌词解析
  • 奇趣点播系统测试报告
  • can‘t set boot order in virtualbox
  • 深入解析B站androidApp接口:从bilibili.api.ticket.v1.Ticket/GetTicket到SendMsg的技术分析
  • java -jar指定类加载
  • 【2025蓝桥杯省赛填空压轴题-pythonA组和研究生组】Ipv6 解析(四维dp)
  • MySQL存储引擎:存储什么意思?引擎什么意思?存储引擎是什么?在MySQL中有什么作用?
  • 马上评|起名“朱雀玄武敕令”?姓名权别滥用
  • 光线传媒:正与部分重点地区洽谈主题乐园合作,首款3A游戏预计三年左右推出
  • 山西省援疆前方指挥部总指挥刘鹓已任忻州市委副书记
  • 特斯拉一季度净利下滑七成,马斯克表态将继续倡导关税下调
  • 2025年一季度上海市生产总值
  • 王励勤当选中国乒乓球协会新一任主席