Linux驱动开发—— IS_ENABLED
在閱讀Linux內核代碼的時候,會經常遇到下面的幾個宏函數:
IS_ENABLED 這個宏最爲常見
IS_BUILTIN
IS_MODULE
IS_REACHABLE
這幾個宏函數是在文件include/linux/kconfig.h中定義的,如下:
/*
* Helper macros to use CONFIG_ options in C/CPP expressions. Note that
* these only work with boolean and tristate options.
*/ /*
* Getting something that works in C and CPP for an arg that may or may
* not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
* we match on the placeholder define, insert the "0," for arg1 and generate
* the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
* When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
* the last step cherry picks the 2nd arg, we get a zero.
*/
#define __ARG_PLACEHOLDER_1 0,
#define config_enabled(cfg) _config_enabled(cfg)
#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
#define ___config_enabled(__ignored, val, ...) val /*
* IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
* 0 otherwise.
*
*/
#define IS_ENABLED(option) \
(config_enabled(option) || config_enabled(option##_MODULE)) /*
* IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
* otherwise. For boolean options, this is equivalent to
* IS_ENABLED(CONFIG_FOO).
*/
#define IS_BUILTIN(option) config_enabled(option) /*
* IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
* otherwise.
*/
#define IS_MODULE(option) config_enabled(option##_MODULE) /*
* IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
* code can call a function defined in code compiled based on CONFIG_FOO.
* This is similar to IS_ENABLED(), but returns false when invoked from
* built-in code when CONFIG_FOO is set to 'm'.
*/
#define IS_REACHABLE(option) (config_enabled(option) || \
(config_enabled(option##_MODULE) && config_enabled(MODULE)))
首先需要有一些基礎知識.
我們知道,在進行內核配置的時候,內核配置若是boolean類型,那麼對應的配置有y和n兩種狀態,如果是tristate,那麼對應的配置有y,n和m三種狀態.
然後,在編譯內核的時候會生成include/generated/autoconf.h
如果某個配置被設置爲了y,那麼在.config文件中:
CONFIG_SND_DUMMY=y
在autoconf.h中會看到:
#define CONFIG_SND_DUMMY 1
如果被設置爲了m,表示這個部分代碼會編譯成內核模塊,那麼在.config中會看到:
CONFIG_SND_DUMMY=m
在autoconf.h中會看到:
#define CONFIG_SND_DUMMY_MODULE 1
可以看到,在宏的末尾多了一個_MODULE的後綴.
如果被設置爲了n,那麼在.config中會看到:
# CONFIG_SND_DUMMY is not set
而在autoconf.h中看不到這個宏的任何定義.
對於靜態編譯到kernel中的文件, 在編譯的時候會宏MODULE不會被定義
而對於編譯到模塊中的文件,在編譯的時候,編譯系統會定義MODULE宏.
下面解釋一下這幾個宏函數的作用
- IS_ENABLED
如果option或者option_MODULE所表示的宏定義在當前上下文被設置爲了1, 那麼這個宏函數會返回1;如果沒有定義或者被定義爲了0, 那麼就返回0.
無論CONFIG_SND_DUMMY被設置爲了y還是m,IS_ENABLED(CONFIG_SND_DUMMY)都會返回1.
- IS_BUILTIN
如果option所表示的宏定義在當前上下文被設置爲了1, 那麼這個宏函數會返回1;如果沒有定義或者被定義爲了0, 那麼就返回0.
只有CONFIG_SND_DUMMY被設置爲了y,IS_BUILTIN(CONFIG_SND_DUMMY)才會返回1.
- IS_MODULE
如果option_MODULE所表示的宏定義在當前上下文被設置爲了1, 那麼這個宏函數會返回1;如果沒有定義或者被定義爲了0, 那麼就返回0.
只有CONFIG_SND_DUMMY被設置爲了m,IS_MODULE(CONFIG_SND_DUMMY)才會返回1.
- IS_REACHABLE
這個宏函數跟IS_ENABLED的類似, 不同之處是,如果CONFIG_SND_DUMMY被設置爲了m,那麼IS_REACHABLE(CONFIG_SND_DUMMY)在靜態編譯到kernel中的文件中被預處理的時候會返回0,而在編譯到模塊的文件中預處理時會返回0.原因是MODULE宏只有在編譯模塊代碼期間纔會被定義.
下面我們將config_enabled(CONFIG_SND_DUMMY)展開:
如果CONFIG_SND_DUMMY在autoconf.h中被設置爲了1, 那麼展開如下:
___config_enabled(__ARG_PLACEHOLDER_1 1, 0)
再進一步展開
___config_enabled(, , )
最後展開如下:
如果CONFIG_SND_DUMMY在autoconf.h中沒有被設置, 那麼展開如下:
___config_enabled(__ARG_PLACEHOLDER_CONFIG_SND_DUMMY , )
進一步展開如下:
下面用一個簡單的測試程序試試:
a.c
#define __ARG_PLACEHOLDER_1 0,
#define config_enabled(cfg) _config_enabled(cfg)
#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
#define ___config_enabled(__ignored, val, ...) val #define ONE 2
#define TWO 1
#define THREE 0
#define FOUR int main(int argc, char *argv[])
{ int a; if (config_enabled(ONE)) {
a = ;
} if (config_enabled(TWO)) {
a = ;
} if (config_enabled(THREE)) {
a = ;
} if (config_enabled(FOUR)) {
a = ;
} if (config_enabled(FIVE)) {
a = ;
} return ;
}
然後使用gcc的預編譯命令 gcc -E a.c -o a.i 編譯出文件a.i如下:
int main(int argc, char *argv[])
{ int a; if () {
a = ;
} if () {
a = ;
} if () {
a = ;
} if () {
a = ;
} if () {
a = ;
} return ;
}
完.
Linux驱动开发—— IS_ENABLED的更多相关文章
- 嵌入式Linux驱动开发日记
嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...
- 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
- 【转】linux驱动开发的经典书籍
原文网址:http://www.cnblogs.com/xmphoenix/archive/2012/03/27/2420044.html Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书 ...
- Linux驱动开发 -- 打开dev_dbg()
Linux驱动开发 -- 打开dev_dbg() -- :: 分类: LINUX linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函数的实质是调用printk(KER ...
- Linux驱动开发学习的一些必要步骤
1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ...
- 驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
- Linux驱动开发必看详解神秘内核(完全转载)
Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html IT168 技术文档]在开始步入L ...
- Linux内核(17) - 高效学习Linux驱动开发
这本<Linux内核修炼之道>已经开卖(网上的链接为: 卓越.当当.china-pub ),虽然是严肃文学,但为了保证流畅性,大部分文字我还都是斟词灼句,反复的念几遍才写上去的,尽量考虑到 ...
随机推荐
- JS调用Android、Ios原生控件
在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...
- 告别被拒,如何提升iOS审核通过率(上篇)
iOS审核一直是每款移动产品上架苹果商店时面对的一座大山,每次提审都像是一次漫长而又悲壮的旅行,经常被苹果拒之门外,无比煎熬.那么问题来了,我们有没有什么办法准确把握苹果审核准则,从而提升审核的通过率 ...
- Springmvc数据校验
步骤一:导入四个jar包 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...
- Java 线程
线程:线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程.线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源.它与父进程的其他线程共享该进程的所有资 ...
- 【开源】.Net Api开放接口文档网站
开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务 238543768 ApiView .net api的接口文档查看 ...
- 界面设计技法之css布局
css布局之于页面就如同ECMAScript之于JS一般,细想一番,html就如同语文,css就如同数学,js呢,就是物理,有些扯远,这里就先不展开了. 回到主题,从最开始的css到如今的sass(l ...
- CSS 3学习——transition 过渡
以下内容根据官方规范翻译以及自己的理解整理. 1.介绍 这篇文档介绍能够实现隐式过渡的CSS新特性.文档中介绍的CSS新特性描述了CSS属性的值如何在给定的时间内平滑地从一个值变为另一个值. 2.过渡 ...
- Java多态性——分派
一.基本概念 Java是一门面向对象的程序设计语言,因为Java具备面向对象的三个基本特征:封装.继承和多态.这三个特征并不是各自独立的,从一定角度上看,封装和继承几乎都是为多态而准备的.多态性主要体 ...
- JavaScript事件代理和委托(Delegation)
JavaScript事件代理 首先介绍一下JavaScript的事件代理.事件代理在JS世界中一个非常有用也很有趣的功能.当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委 ...
- Android中Activity的四大启动模式实验简述
作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...