使用u SYSCALL_DEFINEx在单个宏定义中包含多个值

使用u SYSCALL_DEFINEx在单个宏定义中包含多个值,c,linux-kernel,c-preprocessor,C,Linux Kernel,C Preprocessor,我试图理解/include/linux/syscall.h中的一段代码,其中宏定义似乎有多个值,每个值之间用分号分隔: 235 #define __SYSCALL_DEFINEx(x, name, ...) \ 236 __diag_push(); \ 237 __diag_ignore(GCC,

我试图理解/include/linux/syscall.h中的一段代码,其中宏定义似乎有多个值,每个值之间用分号分隔:

 235 #define __SYSCALL_DEFINEx(x, name, ...)                                 \
 236         __diag_push();                                                  \
 237         __diag_ignore(GCC, 8, "-Wattribute-alias",                      \
 238                       "Type aliasing is used to sanitize syscall arguments");\
 239         asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
 240                 __attribute__((alias(__stringify(__se_sys##name))));    \
 241         ALLOW_ERROR_INJECTION(sys##name, ERRNO);                        \
 242         static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
 243         asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
 244         asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__))  \
 245         {                                                               \
 246                 long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\
 247                 __MAP(x,__SC_TEST,__VA_ARGS__);                         \
 248                 __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));       \
 249                 return ret;                                             \
 250         }                                                               \
 251         __diag_pop();                                                   \
 252         static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
我以前没见过这个,也找不到任何关于这个的参考。当以这种方式定义时,
\uuu SYSCALL\udefinex(x,name,…)
做什么

其中宏定义似乎有多个值

宏没有任何值。宏是一种令牌操作构造。当预处理器扩展它时,它将(零个或多个)输入令牌转换为输出令牌。输出标记必须是有效的标记,它们甚至不需要是有效的C代码。例如:

#define foo(t) 1 > 0 t 0 : 1
这是一个非常有效的函数,就像宏定义一样。当我们写
foo(;)
foo(3)
时,预处理器将参数替换为它吐出的标记序列。当然,对于我们提供的参数,结果在语法上是无效的C。但是
foo(?)
将导致有效的C


序言的要点是解释那些分号没有任何特殊作用。它们只是宏吐出的标记序列的一部分。该宏被设计为用实现系统调用的一系列声明和函数定义来替换自身。函数体中的声明和语句必须以
结尾。仅此而已。

在本例中,您看到的不是具有多个值的宏定义,而是跨多行的宏定义。因此,基本上,uu SYSCALL_DEFINEx(x,name,…)将被它下面的整个代码块替换(请注意,行末尾的\用于跨越多行,当然,每行代码都应以;)结尾)