宏中未使用的参数会怎样?
What happens to unused parameters in macro?
这个问题来自阅读内核,更具体地说是跟踪宏。我在研究内核模块如何执行二进制、elf 和脚本文件 (fs/exec.c) 时遇到了它们。
出于某种原因,我不记得哪个到达了 tracepoint.h 文件,其中定义了宏 TRACE_EVENT 等。我使用 trace_event 作为示例,因为内核中的跟踪示例使用了这个宏。该示例使用了宏
TRACE_EVENT(foo_bar,
TP_PROTO(const char *foo, int bar, const int *lst,
const char *string, const struct cpumask *mask),
TP_ARGS(foo, bar, lst, string, mask),
TP_STRUCT__entry(
__array( char, foo, 10 )
__field( int, bar )
__dynamic_array(int, list, __length_of(lst))
__string( str, string )
__bitmask( cpus, num_possible_cpus() )
),
TP_fast_assign(
strlcpy(__entry->foo, foo, 10);
__entry->bar = bar;
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,
/*
* Notice here the use of some helper functions. This includes:
*
* __print_symbolic( variable, { value, "string" }, ... ),
*
* The variable is tested against each value of the { } pair. If
* the variable matches one of the values, then it will print the
* string in that pair. If non are matched, it returns a string
* version of the number (if __entry->bar == 7 then "7" is returned).
*/
__print_symbolic(__entry->bar,
{ 0, "zero" },
{ TRACE_SAMPLE_FOO, "TWO" },
{ TRACE_SAMPLE_BAR, "FOUR" },
{ TRACE_SAMPLE_ZOO, "EIGHT" },
{ 10, "TEN" }
),
/*
* __print_flags( variable, "delim", { value, "flag" }, ... ),
*
* This is similar to __print_symbolic, except that it tests the bits
* of the value. If ((FLAG & variable) == FLAG) then the string is
* printed. If more than one flag matches, then each one that does is
* also printed with delim in between them.
* If not all bits are accounted for, then the not found bits will be
* added in hex format: 0x506 will show BIT2|BIT4|0x500
*/
__print_flags(__entry->bar, "|",
{ 1, "BIT1" },
{ 2, "BIT2" },
{ 4, "BIT3" },
{ 8, "BIT4" }
),
/*
* __print_array( array, len, element_size )
*
* This prints out the array that is defined by __array in a nice format.
*/
__print_array(__get_dynamic_array(list),
__get_dynamic_array_len(list) / sizeof(int),
sizeof(int)),
__get_str(str), __get_bitmask(cpus))
);
所以,很自然地,在这之后我找到了 TRACE_EVENT 的定义并找到了这个
#define TRACE_EVENT(name, proto, args, struct, assign, print) \
DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
如您所见,trace_event 宏不使用 print 参数(或参数?),以及 struct 和 assign 参数。
非常清楚地表明宏需要它们,但在它的下面只是调用不需要它们的 declare_trace 宏。
至于宏扩展的其余部分,我觉得还可以,没什么意外的,但是宏的这种特殊用法让我很烦恼。所有其他字段是否有某种用途,或者它们只是......没有任何存在的理由?
正如@pvg 指出的那样,linux/tracepoint.h
只是跟踪点的冰山一角。此 header 仅 声明 适当的函数和类型。这就是为什么它不处理 TRACE_EVENT
.
的一些参数的原因
但是带有跟踪定义的 header 被 处理了两次 (或更多次),下一次 TRACE_EVENT
的所有参数都被处理了。
有关 Linux 内核中跟踪点的更多信息,请参阅 Documentation/trace/tracepoints.txt。
这个问题来自阅读内核,更具体地说是跟踪宏。我在研究内核模块如何执行二进制、elf 和脚本文件 (fs/exec.c) 时遇到了它们。
出于某种原因,我不记得哪个到达了 tracepoint.h 文件,其中定义了宏 TRACE_EVENT 等。我使用 trace_event 作为示例,因为内核中的跟踪示例使用了这个宏。该示例使用了宏
TRACE_EVENT(foo_bar,
TP_PROTO(const char *foo, int bar, const int *lst,
const char *string, const struct cpumask *mask),
TP_ARGS(foo, bar, lst, string, mask),
TP_STRUCT__entry(
__array( char, foo, 10 )
__field( int, bar )
__dynamic_array(int, list, __length_of(lst))
__string( str, string )
__bitmask( cpus, num_possible_cpus() )
),
TP_fast_assign(
strlcpy(__entry->foo, foo, 10);
__entry->bar = bar;
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,
/*
* Notice here the use of some helper functions. This includes:
*
* __print_symbolic( variable, { value, "string" }, ... ),
*
* The variable is tested against each value of the { } pair. If
* the variable matches one of the values, then it will print the
* string in that pair. If non are matched, it returns a string
* version of the number (if __entry->bar == 7 then "7" is returned).
*/
__print_symbolic(__entry->bar,
{ 0, "zero" },
{ TRACE_SAMPLE_FOO, "TWO" },
{ TRACE_SAMPLE_BAR, "FOUR" },
{ TRACE_SAMPLE_ZOO, "EIGHT" },
{ 10, "TEN" }
),
/*
* __print_flags( variable, "delim", { value, "flag" }, ... ),
*
* This is similar to __print_symbolic, except that it tests the bits
* of the value. If ((FLAG & variable) == FLAG) then the string is
* printed. If more than one flag matches, then each one that does is
* also printed with delim in between them.
* If not all bits are accounted for, then the not found bits will be
* added in hex format: 0x506 will show BIT2|BIT4|0x500
*/
__print_flags(__entry->bar, "|",
{ 1, "BIT1" },
{ 2, "BIT2" },
{ 4, "BIT3" },
{ 8, "BIT4" }
),
/*
* __print_array( array, len, element_size )
*
* This prints out the array that is defined by __array in a nice format.
*/
__print_array(__get_dynamic_array(list),
__get_dynamic_array_len(list) / sizeof(int),
sizeof(int)),
__get_str(str), __get_bitmask(cpus))
);
所以,很自然地,在这之后我找到了 TRACE_EVENT 的定义并找到了这个
#define TRACE_EVENT(name, proto, args, struct, assign, print) \
DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
如您所见,trace_event 宏不使用 print 参数(或参数?),以及 struct 和 assign 参数。
非常清楚地表明宏需要它们,但在它的下面只是调用不需要它们的 declare_trace 宏。
至于宏扩展的其余部分,我觉得还可以,没什么意外的,但是宏的这种特殊用法让我很烦恼。所有其他字段是否有某种用途,或者它们只是......没有任何存在的理由?
正如@pvg 指出的那样,linux/tracepoint.h
只是跟踪点的冰山一角。此 header 仅 声明 适当的函数和类型。这就是为什么它不处理 TRACE_EVENT
.
但是带有跟踪定义的 header 被 处理了两次 (或更多次),下一次 TRACE_EVENT
的所有参数都被处理了。
有关 Linux 内核中跟踪点的更多信息,请参阅 Documentation/trace/tracepoints.txt。