Linux 内核中条件始终为真的三元运算符有什么需求?
What is the need of ternary operator with always true condition in Linux kernel?
说到Linux内核中定义的一些宏函数,
我可以找到一些奇怪的三元运算符,条件总是为真 (1)
#define to_cpumask(bitmap) \
((struct cpumask *)(1 ? (bitmap) \
: (void *)sizeof(__check_is_bitmap(bitmap))))
static inline int __check_is_bitmap(const unsigned long *bitmap)
{
return 1;
}
似乎__check_is_bitmap(bitmap)
函数在任何条件下都不会被调用,因为它是用三元运算符条件1编写的。
看来是为了在编译时检查位图的类型,这个宏函数故意引入了一个函数,__check_is_bitmap
,需要一个无符号长指针参数,尽管它不会被调用。
如果要检查参数类型要求,最好使用内联函数或普通函数。在这种情况下,为什么内核程序员更喜欢 #defined 函数而不是内联函数?
到目前为止我不是内核方面的专家,考虑到这一点,这是我的两分钱:
在我看来,它像是对宏参数 bitmap
的类型安全检查。由于 macros
没有函数的类型安全检查,运算符的第三个操作数用于此目的:
__check_is_bitmap(bitmap)
是 sizeof
的操作数,因此它处于未 未计算的上下文 中。这意味着它永远不会被调用。接下来,然后sizeof
的结果被转换为(void *)
并被丢弃。
这会检查两件事:
__check_is_bitmap(bitmap)
有效。如果 bitmap
可转换为 const unsigned long *
,就会发生这种情况
bitmap
和void *
的类型有共同的类型(条件运算符要求)
If it wants to check the parameter type requirement, it would have
been better to use an inline function or just plain function. Why the
kernel programmers prefer the #defined function compared to inline
function in this case?
inline
在 linux 内核中被禁止。 "Inlining in linux" from kernel.org(2006 年的一篇文章)对此进行了解释:
[in the linux kernel] We don't use the "inline" keyword because it's broken.
[...]
In theory, the keyword to do this is "inline". In practice, this
keyword is broken on newer versions of gcc. Current versions of gcc
turned "inline" into a request (similar to the old "register"
keyword), rendering it essentially useless. These versions of gcc are
free to ignore any such requests to inline functions, as well as to
inline functions without the keyword.
The problem with this is that to be effective, inline functions must
be defined in header files (since inlining is done by the compiler,
not the linker, it must be done on source code not object files). But
even when every use of a function is inlined, an unused non-inline
version of the function can still be produced and linked "just in
case". If multiple .c files #include the same header, this can even
result in multiple non-inline versions of the same function being
passed to the linker.
Earlier attempts to work around this breakage by declaring functions
"static inline" or "extern inline" (instructing the compiler never to
emit a non-inline version of the function, breaking the build if
necessary to detect when the compiler wasn't following instructions)
worked for a while, but were again broken by newer releases of gcc.
但是现代指南encourage short inline functions:
Linux kernel coding style
12) Macros, Enums and RTL
Generally, inline functions are preferable to macros resembling functions.
15) The inline disease
There appears to be a common misperception that gcc has a magic “make
me faster” speedup option called inline. While the use of inlines can
be appropriate (for example as a means of replacing macros, see
Chapter 12), it very often is not [...]
A reasonable rule of thumb is to not put inline at functions that have
more than 3 lines of code in them.
所以看起来 __check_is_bitmap
是过去写的,当时 inline
是不允许的,最近没有人更改它。请注意,这只是猜测。
说到Linux内核中定义的一些宏函数, 我可以找到一些奇怪的三元运算符,条件总是为真 (1)
#define to_cpumask(bitmap) \
((struct cpumask *)(1 ? (bitmap) \
: (void *)sizeof(__check_is_bitmap(bitmap))))
static inline int __check_is_bitmap(const unsigned long *bitmap)
{
return 1;
}
似乎__check_is_bitmap(bitmap)
函数在任何条件下都不会被调用,因为它是用三元运算符条件1编写的。
看来是为了在编译时检查位图的类型,这个宏函数故意引入了一个函数,__check_is_bitmap
,需要一个无符号长指针参数,尽管它不会被调用。
如果要检查参数类型要求,最好使用内联函数或普通函数。在这种情况下,为什么内核程序员更喜欢 #defined 函数而不是内联函数?
到目前为止我不是内核方面的专家,考虑到这一点,这是我的两分钱:
在我看来,它像是对宏参数 bitmap
的类型安全检查。由于 macros
没有函数的类型安全检查,运算符的第三个操作数用于此目的:
__check_is_bitmap(bitmap)
是 sizeof
的操作数,因此它处于未 未计算的上下文 中。这意味着它永远不会被调用。接下来,然后sizeof
的结果被转换为(void *)
并被丢弃。
这会检查两件事:
__check_is_bitmap(bitmap)
有效。如果bitmap
可转换为const unsigned long *
,就会发生这种情况
bitmap
和void *
的类型有共同的类型(条件运算符要求)
If it wants to check the parameter type requirement, it would have been better to use an inline function or just plain function. Why the kernel programmers prefer the #defined function compared to inline function in this case?
inline
在 linux 内核中被禁止。 "Inlining in linux" from kernel.org(2006 年的一篇文章)对此进行了解释:
[in the linux kernel] We don't use the "inline" keyword because it's broken.
[...]
In theory, the keyword to do this is "inline". In practice, this keyword is broken on newer versions of gcc. Current versions of gcc turned "inline" into a request (similar to the old "register" keyword), rendering it essentially useless. These versions of gcc are free to ignore any such requests to inline functions, as well as to inline functions without the keyword.
The problem with this is that to be effective, inline functions must be defined in header files (since inlining is done by the compiler, not the linker, it must be done on source code not object files). But even when every use of a function is inlined, an unused non-inline version of the function can still be produced and linked "just in case". If multiple .c files #include the same header, this can even result in multiple non-inline versions of the same function being passed to the linker.
Earlier attempts to work around this breakage by declaring functions "static inline" or "extern inline" (instructing the compiler never to emit a non-inline version of the function, breaking the build if necessary to detect when the compiler wasn't following instructions) worked for a while, but were again broken by newer releases of gcc.
但是现代指南encourage short inline functions:
Linux kernel coding style
12) Macros, Enums and RTL
Generally, inline functions are preferable to macros resembling functions.
15) The inline disease
There appears to be a common misperception that gcc has a magic “make me faster” speedup option called inline. While the use of inlines can be appropriate (for example as a means of replacing macros, see Chapter 12), it very often is not [...]
A reasonable rule of thumb is to not put inline at functions that have more than 3 lines of code in them.
所以看起来 __check_is_bitmap
是过去写的,当时 inline
是不允许的,最近没有人更改它。请注意,这只是猜测。