Linux 内核配置机制(make menuconfig、Kconfig、makefile)讲解

前面我们介绍模块编程的时候介绍了驱动进入内核有两种方式:模块和直接编译进内核,并介绍了模块的一种编译方式——在一个独立的文件夹通过makefile配合内核源码路径完成

那么如何将驱动直接编译进内核呢?

    在我们实际内核的移植配置过程中经常听说的内核裁剪又是怎么麽回事呢?

我们在进行linux内核配置的时候经常会执行make menuconfig这个命令,然后屏幕上会出现以下界面:

这个界面是怎么生成的呢?

跟我们经常说的内核配置与与编译又有什么关系呢?

下面我们借此来讲解一下linux内核的配置机制及其编译过程。

一、配置系统的基本结构

Linux内核的配置系统由三个部分组成,分别是:

 1、Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则;

    2、配置文件(config.in(2.4内核,2.6内核)):给用户提供配置选择的功能;

    3、配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图形界面以及基于 Xwindows 图形界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。

这些配置工具都是使用脚本语言,如 Tcl/TK、Perl 编写的(也包含一些用 C 编写的代码)。本文并不是对配置系统本身进行分析,而是介绍如何使用配置系统。所以,除非是配置系统的维护者,一般的内核开发者无须了解它们的原理,只需要知道如何编写 Makefile 和配置文件就可以。

二、makefile menuconfig过程讲解

当我们在执行make menuconfig这个命令时,系统到底帮我们做了哪些工作呢?

这里面一共涉及到了一下几个文件我们来一一讲解

Linux内核根目录下的scripts文件夹

arch/$ARCH/Kconfig文件、各层目录下的Kconfig文件

Linux内核根目录下的makefile文件、各层目录下的makefile文件

Linux内核根目录下的的.config文件、arm/$ARCH/下的config文件

Linux内核根目录下的 include/generated/autoconf.h文件

1)scripts文件夹存放的是跟make menuconfig配置界面的图形绘制相关的文件,我们作为使用者无需关心这个文件夹的内容

 

2)当我们执行make menuconfig命令出现上述蓝色配置界面以前,系统帮我们做了以下工作:

    首先系统会读取arch/$ARCH/目录下的Kconfig文件生成整个配置界面选项(Kconfig是整个linux配置机制的核心),那么ARCH环境变量的值等于多少呢?

它是由linux内核根目录下的makefile文件决定的,在makefile下有此环境变量的定义:

或者通过 make ARCH=arm menuconfig命令来生成配置界面,默认生成的界面是所有参数都是没有值的

比如教务处进行考试,考试科数可能有外语、语文、数学等科,这里相当于我们选择了arm科可进行考试,系统就会读取arm/arm/kconfig文件生成配置选项(选择了arm科的卷子),系统还提供了x86科、milps科等10几门功课的考试题

3)假设教务处比较“仁慈”,为了怕某些同学做不错试题,还给我们准备了一份参考答案(默认配置选项),存放在arch/$ARCH/configs下,对于arm科来说就是arch/arm/configs文件夹:

此文件夹中有许多选项,系统会读取哪个呢?内核默认会读取linux内核根目录下.config文件作为内核的默认选项(试题的参考答案),我们一般会根据开发板的类型从中选取一个与我们开发板最接近的系列到Linux内核根目录下(选择一个最接近的参考答案)

#cp arch/arm/configs/s3c2410_defconfig .config

4).config

    假设教务处留了一个心眼,他提供的参考答案并不完全正确(.config文件与我们的板子并不是完全匹配),这时我们可以选择直接修改.config文件然后执行make menuconfig命令读取新的选项

    但是一般我们不采取这个方案,我们选择在配置界面中通过空格、esc、回车选择某些选项选中或者不选中,最后保存退出的时候,Linux内核会把新的选项(正确的参��答案)更新到.config中,此时我们可以把.config重命名为其它文件保存起来(当你执行make distclean时系统会把.config文件删除),以后我们再配置内核时就不需要再去arch/arm/configs下考取相应的文件了,省去了重新配置的麻烦,直接将保存的.config文件复制为.config即可.

5)经过以上两步,我们可以正确的读取、配置我们需要的界面了

那么他们如何跟makefile文件建立编译关系呢?

当你保存make menuconfig选项时,系统会除了会自动更新.config外,还会将所有的选项以宏的形式保存在

Linux内核根目录下的 include/generated/autoconf.h文件下

内核中的源代码就都会包含以上.h文件,跟宏的定义情况进行条件编译。

当我们需要对一个文件整体选择如是否编译时,还需要修改对应的makefile文件,例如:

    我们选择是否要编译s3c2410_ts.c这个文件时,makefile会根据CONFIG_TOUCHSCREEN_S3C2410来决定是编译此文件,此宏是在Kconfig文件中定义,当我们配置完成后,会出现在.config及autconf中,至此,我们就完成了整个linux内核的编译过程。

    最后我们会发现,整个linux内核配置过程中,留给用户的接口其实只有各层Kconfig、makefile文件以及对应的源文件。

    比如我们如果想要给内核增加一个功能,并且通过make menuconfig控制其声称过程

    首先需要做的工作是:修改对应目录下的Kconfig文件,按照Kconfig语法增加对应的选项;

    其次执行make menuconfig选择编译进内核或者不编译进内核,或者编译为模块,.config文件和autoconf.h文件会自动生成;

    最后修改对应目录下的makefile文件完成编译选项的添加;

    最后的最后执行make zImage命令进行编译。

三、具体实例

下面我们以前面做过的模块实验为例,讲解如何通过make menuconfig机制将前面单独编译的模块编译进内核或编译为模块

假设我已经有了这么一个驱动:

modules.c

  1. #include <linux/module.h>       /*module_init()*/
  2. #include <linux/kernel.h> /* printk() */
  3. #include <linux/init.h>       /* __init __exit */
  4. #define DEBUG   //open debug message
  5. #ifdef DEBUG
  6. #define PRINTK(fmt, arg...)     printk(KERN_WARNING fmt, ##arg)
  7. #else
  8. #define PRINTK(fmt, arg...)     printk(KERN_DEBUG fmt, ##arg)
  9. #endif
  10. /* Module Init & Exit function */
  11. static int __init myModule_init(void)
  12. {
  13. /* Module init code */
  14. PRINTK("myModule_init\n");
  15. return 0;
  16. }
  17. static void __exit myModule_exit(void)
  18. {
  19. /* Module exit code */
  20. PRINTK("myModule_exit\n");
  21. return;
  22. }
  23. module_init(myModule_init);
  24. module_exit(myModule_exit);
  25. MODULE_AUTHOR("dengwei");                          /*模块作者,可选*/
  26. MODULE_LICENSE("GPL");                             /*模块许可证明,描述内核模块的许可权限,必须*/
  27. MODULE_DESCRIPTION("A simple Hello World Module"); /*模块说明,可选*/
Step1:将modules.c拷到drivers/char/目录下(这个文件夹一般存放常见的字符驱动)
 
Step2: vi driver/char/Kconfig,在
    config DEVKMEM后添加以下信息
 
config MODULES
tristate "modules device support"
default y
help
 Say Y here,the modules will be build in kernel.
 Say M here,the modules willbe build to modules.
 Say N here,there will be nothing to be do. 
 
Step3:make menuconfig 
     Device driver-character devices
           [*]modules device suppor
 
Step4:vi driver/char/Makefile,在js-rtc后添加
obj-$(CONFIG_MODULES)+= modules.o

CONFIG_MODULES 必须跟上面的Kconfig中保持一致,系统会自动添加CONFIG_前缀

modules.o必须跟你加入的.c文件名一致

最后执行:make zImage modules就会被编译进内核中

第三步:

Step3:make menuconfig
     Device driver-character devices
           [M]modules device suppor

把星号在配置界面通过空格改为M,最后执行make modules,在driver/char/目录下会生成一个modules.ko文件

跟我们前面讲的单独编译模块效果一样,也会生成一个模块,将它考入开发板执行insmod moudles.ko,即可将生成的模块插入内核使用。

Linux驱动基础开发的更多相关文章

  1. linux驱动基础系列--linux spi驱动框架分析

    前言 主要是想对Linux 下spi驱动框架有一个整体的把控,因此会忽略某些细节,同时里面涉及到的一些驱动基础,比如平台驱动.设备模型等也不进行详细说明原理.如果有任何错误地方,请指出,谢谢! spi ...

  2. linux驱动基础系列--linux spi驱动框架分析(续)

    前言 这篇文章是对linux驱动基础系列--linux spi驱动框架分析的补充,主要是添加了最新的linux内核里设备树相关内容. spi设备树相关信息 如之前的文章里所述,控制器的device和s ...

  3. linux驱动基础系列--Linux mmc sd sdio驱动分析

    前言 主要是想对Linux mmc子系统(包含mmc sd sdio)驱动框架有一个整体的把控,因此会忽略某些细节,同时里面涉及到的一些驱动基础,比如平台驱动.块设备驱动.设备模型等也不进行详细说明原 ...

  4. linux驱动基础系列--Linux 串口、usb转串口驱动分析

    前言 主要是想对Linux 串口.usb转串口驱动框架有一个整体的把控,因此会忽略某些细节,同时里面涉及到的一些驱动基础,比如字符设备驱动.平台驱动等也不进行详细说明原理.如果有任何错误地方,请指出, ...

  5. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  6. linux驱动基础系列--Linux I2c驱动分析

    前言 主要是想对Linux I2c驱动框架有一个整体的把控,因此会忽略协议上的某些细节,同时里面涉及到的一些驱动基础,比如平台驱动.设备模型.sysfs等也不进行详细说明原理,涉及到i2c协议部分也只 ...

  7. linux驱动基础系列--linux rtc子系统

    前言 linux驱动子系统太多了,连时钟也搞了个子系统,这导致一般的时钟芯片的驱动也会涉及到至少2个子系统,一个是时钟芯片接口子系统(比如I2c接口的时钟芯片),一个是内核给所有时钟芯片提供的rtc子 ...

  8. Linux驱动基础:MSM平台AP/CP通信机制

    点击打开链接 概述 MSM平台AP和CP封装到一个芯片,共享内容.所以之前也说过,高通的MSM解决方案中,CP的代码都是由AP放到指定地址的内存中以供CP运行.那上传完代码,CP开始跑之后,AP/CP ...

  9. Linux驱动基础:msm平台,modem等framework加载

    msm平台,AP和CP封装在一起,公用一块内存.所以AP需要负责把整个modem, TZ , rpm等binary拷贝到内存中以供modem等subsystem去运行.那AP这边是怎么分配这些内存,又 ...

随机推荐

  1. 【Java_基础】空串、空格串、null的区别

    1.表示的区别 string str1 = "";    //空串      str1.length() 等于 0 string str2 = " ";   / ...

  2. MariaDB数据库(四)

    1. 数据库备份与恢复 数据库备份用命令mysqldump ,MySQL的备份文件一般以.sql结尾,做到见名知意 #备份testdb数据库重定向为testdb.sql文件, [root@localh ...

  3. Python编程快速上手--实践项目11.11.1

    from selenium import webdriver from selenium.webdriver.common.keys import Keys import time def messa ...

  4. LeetCode(112) Path Sum

    题目 Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up ...

  5. JavaScript正则表达式-字符类

    字符列表 在方括号内指定一个或者多个字符组成的字符列表,与字符列表中任意字符匹配,都被认为是匹配的.每次匹配只能匹配列表中的一个字符. str = "bird,head,fed,meadow ...

  6. 安装mongodb卡顿

    "3.6下载安装会卡死."的原因在于,默认安装是包含mongodb compass,这个包的,这个包大约有180MB,下载很慢,导致所谓的的”卡死“. 如果你选用自定义安装的并且不 ...

  7. python红包随机生成(隔板法)

    #红包生成思路#200 块钱 10个红包#0-200 的一个轴,随机取9个点,分成10段, 每一段的值表示一个红包的大小 #把输入的 money值 * 100 拿到的数值就是分, 不用再考虑单位是元的 ...

  8. js/jquery判断浏览器 & 停止加载

    JS获取浏览器信息 复制代码代码如下: 浏览器代码名称:navigator.appCodeName浏览器名称:navigator.appName浏览器版本号:navigator.appVersion对 ...

  9. Linux下制作不用密码可立即登录的SSH用户

    一.客户端建立两把钥匙 (1)本例以客户端的monkey用户为例,首先切换到~/.ssh目录下,如果没有该目录的话,需要进行新建 cd ~ mkdir .ssh chmod 700 .ssh cd ~ ...

  10. websphere8.5 与cxf2.x冲突问题

    一个客户was部署的小问题,记录一下. 问题现象 在我们的服务中用调用别人的webservice服务报错,框架用的cxf. 报错关键信息有: E com.ibm.ws.webcontainer.web ...