Linux kernel中的IS_ENABLED

本文详细解析了Linux内核中如何通过IS_ENABLED宏检测Kconfig选项的状态。当配置项被激活时,对应的宏定义会在自动生成的autoconfig.h中声明,并通过一系列宏展开逻辑判断配置项是否有效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在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选项配置为ym, 并且timer->is_rel不为0时调用rem -= hrtimer_resolution.
那么这个是怎样实现的呢?
首先在Kconfig中选中某个选项为ym时, 在.config文件中就会由一个CONFIG_XXXXX=yCONFIG_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.

ld.lld: error: undefined symbol: kasan_init_hw_tags >>> referenced by smp.c:471 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/smp.c:471) >>> vmlinux.o:(smp_prepare_boot_cpu) ld.lld: error: undefined symbol: __kasan_cache_create_kmalloc >>> referenced by kasan.h:143 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:143) >>> vmlinux.o:(create_kmalloc_cache) ld.lld: error: undefined symbol: kasan_flag_enabled >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0xE58) >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0xE88) >>> referenced by irqbypass.c >>> vmlinux.o:(__jump_table+0x5FD8) >>> referenced 894 more times ld.lld: error: undefined symbol: kasan_init_hw_tags_cpu >>> referenced by cpufeature.c:1877 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/cpufeature.c:1877) >>> vmlinux.o:(cpu_enable_mte) ld.lld: error: undefined symbol: kasan_report_async >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_check_tfsr_el1) >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_thread_switch) >>> referenced by mte.c:187 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/kernel/mte.c:187) >>> vmlinux.o:(mte_suspend_enter) ld.lld: error: undefined symbol: kasan_report >>> referenced by fault.c:334 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/arch/arm64/mm/fault.c:334) >>> vmlinux.o:(__do_kernel_fault) ld.lld: error: undefined symbol: __kasan_unpoison_range >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(dup_task_struct) >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(mempool_exit) >>> referenced by kasan.h:111 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:111) >>> vmlinux.o:(remove_element) >>> referenced 3 more times ld.lld: error: undefined symbol: __kasan_unpoison_vmalloc >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(scs_alloc) >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(scs_free) >>> referenced by kasan.h:416 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:416) >>> vmlinux.o:(vm_map_ram) >>> referenced 2 more times ld.lld: error: undefined symbol: __kasan_poison_vmalloc >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(scs_alloc) >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(vm_unmap_ram) >>> referenced by kasan.h:425 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:425) >>> vmlinux.o:(__vunmap) ld.lld: error: undefined symbol: __kasan_unpoison_pages >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(mempool_exit) >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(remove_element) >>> referenced by kasan.h:127 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:127) >>> vmlinux.o:(mempool_resize) >>> referenced 4 more times ld.lld: error: undefined symbol: __kasan_poison_pages >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_init_node) >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_resize) >>> referenced by kasan.h:119 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:119) >>> vmlinux.o:(mempool_free) >>> referenced 2 more times ld.lld: error: undefined symbol: __kasan_slab_free_mempool >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_init_node) >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_resize) >>> referenced by kasan.h:208 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:208) >>> vmlinux.o:(mempool_free) ld.lld: error: undefined symbol: __kasan_never_merge >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(slab_unmergeable) >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(find_mergeable) >>> referenced by kasan.h:103 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:103) >>> vmlinux.o:(find_mergeable) ld.lld: error: undefined symbol: __kasan_kmalloc_large >>> referenced by kasan.h:237 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:237) >>> vmlinux.o:(kmalloc_order) ld.lld: error: undefined symbol: __kasan_check_byte >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(krealloc) >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(kfree_sensitive) >>> referenced by kasan.h:259 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:259) >>> vmlinux.o:(ksize) ld.lld: error: undefined symbol: __kasan_krealloc >>> referenced by kasan.h:247 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:247) >>> vmlinux.o:(krealloc) ld.lld: error: undefined symbol: kasan_free_pages >>> referenced by page_alloc.c:1361 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:1361) >>> vmlinux.o:(__free_pages_ok) >>> referenced by page_alloc.c:1361 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:1361) >>> vmlinux.o:(free_unref_page_prepare) ld.lld: error: undefined symbol: kasan_alloc_pages >>> referenced by page_alloc.c:2410 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:2410) >>> vmlinux.o:(post_alloc_hook) >>> referenced by page_alloc.c:2410 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/mm/page_alloc.c:2410) >>> vmlinux.o:(prep_new_page) ld.lld: error: undefined symbol: __kasan_metadata_size >>> referenced by kasan.h:150 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:150) >>> vmlinux.o:(print_trailer) >>> referenced by kasan.h:150 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:150) >>> vmlinux.o:(check_object) ld.lld: error: undefined symbol: __kasan_kmalloc >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(kmem_cache_alloc_trace) >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(__kmalloc) >>> referenced by kasan.h:227 (/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/include/linux/kasan.h:227) >>> vmlinux.o:(__kmalloc_track_caller) ld.lld: error: too many errors emitted, stopping now (use --error-limit=0 to see all errors) make[1]: *** [/home/lhl/ga-4.1/repo_code/out/oriole/kernel/src_tmp/linux-5.15/Makefile:1277: vmlinux] Error 1 make[1]: Leaving directory '/home/lhl/ga-4.1/repo_code/out/oriole/kernel/OBJ/linux-5.15' make: *** [Makefile:237: __sub-make] Error 2
最新发布
07-22
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值