Linux kernel中的IS_ENABLED
阿新 • • 發佈:2019-01-08
在kernel的程式碼中, 有時候會看見IS_ENABLED(CONFIG_XXXX)
來測試某個Kconfig選項是否開啟(即選中為y
或者m
). 如
if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel)
rem -= hrtimer_resolution;
這裡當TIME_LOW_RES這個Kconfig選項配置為y
或m
, 並且timer->is_rel
不為0時呼叫rem -= hrtimer_resolution
.
那麼這個是怎樣實現的呢?
首先在Kconfig中選中某個選項為y
或m
時, 在.config
CONFIG_XXXXX=y
或CONFIG_XXXXX=m
, 並且會自動生成一個頭檔案autoconfig.h
. 當選中為y
時, 標頭檔案中包含#define CONFIG_XXXXX 1
, 當選中為m
時, 標頭檔案中包含#define CONFIG_XXXXX_MODULE 1
, 當不選中是, 標頭檔案中不包含相關語句. IS_ENABLED
定義為
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
IS_BUILTIN
, IS_MODULE
和__or
分別定義為
#define IS_BUILTIN(option) __is_defined(option)
#define IS_MODULE(option) __is_defined(option##_MODULE)
#define __or(x, y) ___or(x, y)
#define ___or(x, y) ____or(__ARG_PLACEHOLDER_##x, y)
#define ____or(arg1_or_junk, y) __take_second_arg(arg1_or_junk 1, y)
__is_defined
定義為
#define __is_defined(x) ___is_defined(x)
#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
在這之前定義了
#define __ARG_PLACEHOLDER_1 0,
#define __take_second_arg(__ignored, val, ...) val
當#define CONFIG_XXXXX 1
時__is_defined(1)
展開為____is_defined(0,)
, 即__take_second_arg(0, 1, 0)
, 最終為1
當CONFIG_XXXXX
沒有定義時__is_defined()
展開為____is_defined()
(因為沒有定義__ARG_PLACEHOLDER_), 即__take_second_arg(1, 0)
, 最終為0
同樣的方法可以理解__or
.
因此IS_ENABLED
主要是將沒有定義的CONFIG_XXXXX
對映到0.