Tracepoint 的实现很大一部分是依赖于宏来实现的,但是里面曾经出现不少的patch说明正确使用宏的确是不容易的事情。下面是阅读几个patch的体会。
case 1:
以include/trace/events/sched.h 为例:
#undef TRACE_SYSTEM
#define TRACE_SYSTEM sched
#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_SCHED_H
#include
#include
…....(此处为省略内容)
#endif /* _TRACE_SCHED_H */
/* This part must be outside protection */
#include
而在以前,最前面三行
#undef TRACE_SYSTEM
#define TRACE_SYSTEM raw_syscalls
#define TRACE_INCLUDE_FILE syscalls
一般是放在#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)和#endif 里面,为什么移出来呢?见.
未有补丁之前,假设一个C文件先后执行下面三个#include语句:
#include
-> TRACE_SYSTEM == sched
...
#include
-> TRACE_SYSTEM == bar
...
#define CREATE_TRACE_POINTS
#include
-> TRACE_SYSTEM == bar !!!
前面两个#include导致的结果容易理解,而且第一个导致了_TRACE_SCHED_H被定义,所以第三个#include直接会跳过
#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
…....(此处为省略内容)
#endif /* _TRACE_SCHED_H */
部分,也就是TRACE_SYSTEM没有改变。注意TRACE_HEADER_MULTI_READ 是在trace/define_trace.h中定义,现在还未露面,所以上面#if条件为假 。
由此看出,移出是有必要的。
附带说明一下,上面的说明同样适用于trace/events/sched.h的最后两行:
/* This part must be outside protection */
#include
试想一下如下的#include系列
#include
…....(此处为省略内容)
#define CREATE_TRACE_POINTS
#include
如果放入#if 保护,则第二次的#include无法激活trace/define_trace.h使得CREATE_TRACE_POINTS派上用场。
下面的patch原因也非常类似。
case 2:第二个patch简单一些,见
tracepoint 都会用到include/linux/tracepoint.h中TRACE_EVENT宏,而该宏是位于
#ifndef _LINUX_TRACEPOINT_H. 这样的话如下的场景有问题:
#define CREATE_TRACE_POINTS
#include
#include
上述场景是连续定义两个tracepoint, 注意文件的尾部有如下两行保证了连续定义。
/* We may be processing more files */
#define CREATE_TRACE_POINTS
解决的步骤
(1) 将TRACE_EVENT宏 移出#ifndef _LINUX_TRACEPOINT_H 的保护
(2)
不让#include
中产生的TRACE_EVENT定义影响中的TRACE_EVENT定义,即避免re-defined macro 问题。为此要在文件后面加上#undef TRACE_EVENT
case 3:
这个patch更加奇怪,竟然在文件中要#include似乎不相干的文件,下面是patch的内容:
/*
* module.h includes tracepoints, and because ftrace.h
* pulls in module.h:
* trace/ftrace.h -> linux/ftrace_event.h -> linux/perf_event.h ->
* linux/ftrace.h -> linux/module.h
* we must include module.h here before we play with any of
* the TRACE_EVENT() macros, otherwise the tracepoints included
* by module.h may break the build.
*/
#include
文件内容如下,可以看到包含了。
#ifndef _LINUX_MODULE_H
#define _LINUX_MODULE_H
#include
#include
…....(此处为省略内容)
#endif /* _LINUX_MODULE_H */
从
注释来看,#include 可能导致#include
,从而可能触发#include
中的tracepoint,导致不期望的结果。在define_trace.h首
部#include ,将#define
_LINUX_MODULE_H,避免上述情况的发生。这个bug之所以以前没有被发现是因为“We have been lucky so far
that this has not broke the build
since module.h is included in almost everything.”
总体来说,围绕着tracepoint的宏的确复杂,也不容易控制,这也是patch不断出现的原因。
阅读(3404) | 评论(0) | 转发(0) |