Linux中的IS_ENABLED 函数实战使用demo

IS_ENABLED 函数详解

IS_ENABLED() 是 Linux 内核中一个非常重要的预处理宏,用于检查内核配置选项是否被启用。它定义在 include/linux/kconfig.h 文件中。

函数定义

复制代码
/*
 * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
 * 0 otherwise.
 */
#define IS_ENABLED(option) \
    (__is_defined(option) || __is_defined(option##_MODULE))

工作原理

IS_ENABLED() 可以检查三种状态:

  • y:编译进内核(built-in)

  • m:编译为内核模块(module)

  • 未设置:未启用

++当配置选项为 ym 时返回 1,否则返回 0。++

使用示例

1. 基本用法

复制代码
#include <linux/kconfig.h>


// 检查 CONFIG_USB 是否启用(无论是 y 还是 m)
if (IS_ENABLED(CONFIG_USB)) {
    // USB 相关的代码
    usb_init();
}


// 检查 CONFIG_DEBUG_FS 是否启用
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
    debugfs_create_file("myfile", 0644, NULL, NULL, &my_fops);
}

2. 条件编译 vs 运行时检查

复制代码
// 方式1:条件编译(预处理阶段)
#ifdef CONFIG_USB
    usb_init();  // 如果未配置,这段代码完全不存在
#endif

// 方式2:运行时检查(编译阶段)
if (IS_ENABLED(CONFIG_USB)) {
    usb_init();  // 代码总是存在,但可能不会执行
}

3. 实际驱动示例

复制代码
static int my_driver_probe(struct platform_device *pdev)
{
    int ret;
    
    // 检查是否启用了调试功能
    if (IS_ENABLED(CONFIG_MY_DRIVER_DEBUG)) {
        dev_info(&pdev->dev, "Debug mode enabled\n");
        my_driver_enable_debug();
    }
    
    // 检查是否支持电源管理
    if (IS_ENABLED(CONFIG_PM)) {
        device_init_wakeup(&pdev->dev, true);
    }
    
    // 根据配置决定使用哪种模式
    if (IS_ENABLED(CONFIG_MY_DRIVER_DMA)) {
        ret = my_driver_init_dma(pdev);
    } else {
        ret = my_driver_init_pio(pdev);
    }
    
    return ret;
}

与其他宏的区别

检查范围 使用场景 示例
IS_ENABLED() y 或 m 运行时检查配置是否可用 if (IS_ENABLED(CONFIG_USB))
IS_BUILTIN() 仅 y 检查是否编译进内核 if (IS_BUILTIN(CONFIG_USB))
IS_MODULE() 仅 m 检查是否编译为模块 if (IS_MODULE(CONFIG_USB))
#ifdef 任何定义 编译时条件包含代码 #ifdef CONFIG_USB

需求:找不到/dev/ttyS0 串口设备节点

原因是不同的板卡配置的时候,采用的是不同的需求,有些又需要/dev/ttyS2,所以同一份sdk中的串口驱动,得实现根据不同的板卡配置,给创建不同的串口节点。所以这时候IS_ENABLE()函数的作用就来了,

大概原理是在内核配置文件中增加宏定义,根据不同的板卡需要则打开那个即可,不需要的则采用用默认的即可,如下述代码demo,全部贴上来了,感觉还蛮实用的。

复制代码
hzs@sr658:~/rk3562-v1.2.0-sdk/kernel$ git diff ./
diff --git a/arch/arm64/configs/rk3562_scd1_mono_defconfig b/arch/arm64/configs/rk3562_scd1_mono_defconfig
index 04c0afb9c95b..044b6c07d9b1 100644
--- a/arch/arm64/configs/rk3562_scd1_mono_defconfig
+++ b/arch/arm64/configs/rk3562_scd1_mono_defconfig
@@ -246,6 +246,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=10
 CONFIG_SERIAL_8250_RUNTIME_UARTS=10
 CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_DW_TTYS0=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ROCKCHIP=y
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 2aa42e1a85b3..e2bf6f372048 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -449,10 +449,14 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)

                /* get index of serial line, if found in DT aliases */
                id = of_alias_get_id(np, "serial");
-               if (id >= 0) {
+               if (IS_ENABLED(CONFIG_SERIAL_8250_DW_TTYS0)) {
+                       printk("[%s]000 id = %d CONFIG_SERIAL_8250_DW_TTYS0 = %d \n", __func__, id, CONFIG_SERIAL_8250_DW_TTYS0);
+                       p->line = 0;
+               }else{
+                       printk("[%s]111 id = %d CONFIG_SERIAL_8250_DW_TTYS0 = %d \n", __func__, id, CONFIG_SERIAL_8250_DW_TTYS0);
                        p->line = id;
-               //      p->line = 0;
                }
+
                if (IS_ENABLED(CONFIG_ROCKCHIP_MINI_KERNEL))
                        return;

diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index b7922c8da1e6..86dcc0963a82 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -376,6 +376,14 @@ config SERIAL_8250_DW
          Selecting this option will enable handling of the extra features
          present in the Synopsys DesignWare APB UART.

+config SERIAL_8250_DW_TTYS0
+       tristate "Support for Synopsys DesignWare 8250 quirks"
+       depends on SERIAL_8250
+       select SERIAL_8250_DWLIB
+       help
+         Selecting this option will enable handling of the extra features
+         present in the Synopsys DesignWare APB UART.
+
 config SERIAL_8250_EM
        tristate "Support for Emma Mobile integrated serial port"
        depends on SERIAL_8250 && ARM && HAVE_CLK
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index a8bfb654d490..2e866fc1a8a6 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_SERIAL_8250_HUB6)                += 8250_hub6.o
 obj-$(CONFIG_SERIAL_8250_FSL)          += 8250_fsl.o
 obj-$(CONFIG_SERIAL_8250_MEN_MCB)      += 8250_men_mcb.o
 obj-$(CONFIG_SERIAL_8250_DW)           += 8250_dw.o
+obj-$(CONFIG_SERIAL_8250_DW_TTYS0)     += 8250_dw.o
 obj-$(CONFIG_SERIAL_8250_EM)           += 8250_em.o
 obj-$(CONFIG_SERIAL_8250_IOC3)         += 8250_ioc3.o
 obj-$(CONFIG_SERIAL_8250_OMAP)         += 8250_omap.o
hzs@sr658:~/rk3562-v1.2.0-sdk/kernel$
相关推荐
源远流长jerry2 小时前
软件定义网络 SDN 核心技术深度解析:从概念到实践
linux·网络·架构
橙露2 小时前
Linux 服务器性能排查:CPU / 内存 / 磁盘 / 网络一键定位
linux·服务器·网络
ytttr8732 小时前
MAX31856热电偶采集芯片参考代码(STM32实现)
stm32·单片机·嵌入式硬件
暴力求解2 小时前
Linux---命名管道与共享内存(一)
linux·运维·服务器
小鸡食米2 小时前
Linux 防火墙
linux·运维·服务器
海盗猫鸥2 小时前
「Linux工具」自动化构建make/Makfile
linux
星晨雪海2 小时前
MyBatis-Plus 常用 CRUD 方法大全
linux·tomcat·mybatis
2739920292 小时前
Ubuntu 文件系统修复指南
linux·ubuntu·fsck
jghhh013 小时前
九齐单片机2路PWM控制输出实现指南
单片机·嵌入式硬件