我们在使用make menuconfig这个命令的时候,屏幕上会出现配置界面:
那么,我们输入make menuconfig命令以后,在界面出现以前,系统做了哪些事情呢(两件事情)?
1、menuconfig读取Kconfig文件的项目内容:
1)、menuconfig显示的菜单内容(菜单的目录结构、每一个菜单项目的细节),由内核源码树各个目录下的Kconfig文件来提供(Kconfig是整个linux配置机制的核心)。
a、Kconfig文件中按照一定的格式包含一些配置项,每一个配置项在make menuconfig中都会成为一个菜单项目。
b、menuconfig中显示的菜单目录结构和源码目录中的Kconfig的目录结构是一样的。
2)、在相应的Kconfig文件中删除一个配置项,则再次make menuconfig时,此配置项不再存在。
2、menuconfig读取/写入.config文件的选择值:
1)menuconfig的菜单内容来自于Kconfig文件,Kconfig文件是不变的,Kconfig文件只是决定有没有这个菜单项,并不管这个菜单项的选择结果。
(2)在make menuconfig时,会读取.config文件,并且用.config文件中的配置选择结果(Y、N、M)来初始化menuconfig中各个菜单项的选择值。
(3)当我们每次退出make menuconfig时
menuconfig机制会首先检查我们有没有更改某些配置项的值,如果我们本次没有更改过任意一个配置项目的值那直接退出;
如果我们有改动配置项的值则会提示我们是否保存;
此时如果点保存,则会将我们更改过的配置重新写入.config文件中记录;
下一次再次打开make menuconfig时会再次加载.config,最终去编译内核时编译连接程序会考虑.config中的配置值,从而指导整个编译连接过程。
总结:菜单项的项目内容从Kconfig文件来,菜单项的选择值从.config文件来。
经过以上两步,我们可以正确的读取、配置我们需要的界面了。
那么他们如何跟makefile文件建立编译关系呢?
1、当你保存make menuconfig选项时,系统会除了会自动更新.config外,还会将所有的选项以宏的形式保存在Linux内核根目录下的 include/generated/autoconf.h文件下
2、当我们需要对一个文件整体选择如是否编译时,还需要修改对应的makefile文件。
(基本指令如下)
obj-y:表示将该文件编译进内核.
obj-m: 表示将该文件编译成模块.
obj-x:不编译。
这里,我们扩展一下,什么是模块。
参考博客:https://blog.csdn.net/xdw1985829/article/details/6832525
1、linux内核模块简介:
linux内核整体结构非常庞大,其包含的组件也非常多。我们怎么把需要的部分都包含在内核中呢?
一种办法是把所有的需要的功能都编译到内核中。这会导致两个问题,一是生成的内核会很大,二是如果我们要在现有的内核中新增或删除功能,不得不重新编译内核,工作效率会非常的低,同时如果编译的模块不是很完善,很有可能会造成内核崩溃。
linux提供了另一种机制来解决这个问题,这种集中被称为模块,可以实现编译出的内核本身并不含有所有功能,而在这些功能需要被使用的时候,其对应的代码可以被动态的加载到内核中。
2、模块特点:
1)模块本身并不被编译入内核,从而控制了内核的大小。
2)模块一旦被加载,他就和内核中的其他部分完全一样。
注意:模块并不是驱动的必要形式:即:驱动不一定必须是模块,有些驱动是直接编译进内核的;同时模块也不全是驱动,例如我们写的一些很小的算法可以作为模块编译进内核,但它并不是驱动。就像烧饼不一定是圆的,圆的也不都是烧饼一样。
扩展:
最后我们会发现,整个linux内核配置过程中,留给用户的接口其实只有各层Kconfig、makefile文件以及对应的源文件。
如果想要给内核增加一个功能(在内核中添加驱动的方法同理),并且通过make menuconfig控制其声明过程:
首先需要做的工作是:修改对应目录下的Kconfig文件,按照Kconfig语法增加对应的选项;
其次通过make menuconfig配置各个菜单项的选择值,.config文件和autoconf.h文件会自动生成;
注:当执行make distclean时,系统会把.config文件删除。切记!!!
最后修改对应目录下的makefile文件,选择编译进内核或者不编译进内核,或者编译为模块完成编译选项的添加;
最后的最后执行make zImage命令进行编译。
总结如下:
这里能够看出Makefile里面的条件编译是由.config中的宏决定的,而.config中的宏是否被注释又是有make menuconfig中选择决定的,而make menuconfig中的是否存在这个配置选项则是由Kconfig决定的,由此串联起来了四者的关系。
实例:
在内核中添加驱动的方法:
1.根据驱动种类在Kconfig中添加menuconfig选项,例如在内核源码目录下的/drivers/char目录中的Kconfig中添加配置选项 HELLO_CTL(在这之前需要在平台文件中添加注册设备的结构体,一般在/arch/arm目录下)
2、这时,输入make menuconfig命令,我们就可以找到添加的选项。
3、勾选以后,我们可以在.config中看到生成了相关的宏。
当我们在menuconfig中把HELLO_CTL 前面的[*] 去掉 改为不编译进内核时,可以看到在.config中的HELLO_CTL的宏会被注释
4.修改Makefile,这里要做的就是在Makefile中添加我们需要编译的源文件,当然这里的Makefile必须要跟你在添加在Kconfig目录在同一级。前提是这个目录下确实要有这个源文件,否侧编译会报错.
5.在内核源码一级目录下 make即可生成添加了驱动的内核镜像zImage
注:参考朱有鹏老师的资料和https://blog.csdn.net/xdw1985829博客主的博客