以2.6.35.7版本的内核为例
总结:.config决定了Make时的条件编译与联接。.config文件由两次配置第一次makeXX_defconfig第二次menuconfig。
1、分析源码目录下的单个文件
(1)Kbuild,Kbuild是kernelbuild的意思,就是内核编译的意思。这个文件就是linux内核特有的内核编译体系须要用到的文件。
(2)Makefile,这个是linux内核的总makefile,整个内核工程用这个Makefile来管理的。
(3)mk,是九鼎在移植时自己添加的,不是linux内核本身的东西。九鼎添加这个文件的作用是用这个文件来整天管理kernel目录的配置和编译,也就是说这个文件有点类似于我们之前移植uboot时自己创建的那种cp.sh。
2、linux内核源码目录结构
(1)arch。arch是architecture的简写,意思是构架。arch目录下是很多个不同构架的CPU的子目录,例如arm这些cpu的所有文件都在arch/arm目录下,X86的CPU的所有文件都在arch/x86目录下。
(2)block。英语是块的意思,在linux中block表示块设备(以块(多个字节组成的整体,类似于磁道)为单位来整体访问),例如说SD卡、iNand、Nand、硬盘等都是块设备。你几乎可以觉得块设备就是储存设备。block目录下放的是一些linux储存体系中关于块设备管理的代码。
(3)crypto。中文意思是加密。这个目录下放了一些各类常见的加密算法的C语言代码实现。例如crc32、md5、sha1等。
(4)Documentation。上面放了一些文档。
(5)drivers。驱动目录,上面分门别类的列举了linux内核支持的所有硬件设备的驱动源代码。
(6)firmware。固件。哪些是固件?固件似乎是软件,不过这个软件是座机到IC上面运行的叫固件。如同S55PVPV210里的iROM代码。
(7)fs。fs就是filesystem,文件系统,上面列举了linux支持的各类文件系统的实现。
(8)include。头文件目录,公共的(各类CPU构架共用的)头文件都在这儿。每种CPU构架特有的一些头文件在arch/arm/include目录及其子目录下。
(9)init。init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码。
(10)ipc。ipc就是interprocesscommuication,进程间通讯,上面都是linux支持的IPC的代码实现。
(11)kernel。kernel就是内核,就是linux内核,所以这个文件夹下放的就是内核本身须要的一些代码文件。
(12)lib。lib是库的意思,这儿面都是一些公用的有用的库函数,注意这儿的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数linux操作系统原理,这儿的lib目录下的库函数就是拿来取代这些标准库函数的。诸如在内核中要把字符串转成数字用atoi,而且内核编程中只能用lib目录下的atoi函数,不能用标准C语言库中的atoi。诸如在内核中要复印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的。
(13)mm。mm是memorymanagement,显存管理,linux的显存管理代码都在这儿。
(14)net。该目录下是网路相关的代码,例如TCP/IP合同栈等都在这儿。
(15)scripts。脚本,这个目录下全部是脚本文件,这种脚本文件不是linux内核工作时使用的,而是拿来辅助对linux内核进行配置编译生产的。我们并不会详尽步入剖析这个目录下的脚本,而是通过外围来重点学会配置和编译linux内核即可。
(16)security。安全相关的代码。不用去管。
(17)sound。音频处理相关的。
(18)tools。linux中用到的一些有用工具
(19)usr。目录下是initramfs相关的,和linux内核的启动有关linux 内核配置文件,暂时不用去管。
(20)virt。内核虚拟机相关的,暂时不用管。
总结:那么多目录跟我们关系很紧密的就是arch和drivers目录,之后其他有点相关的还有include、block、mm、net、lib等目录。
3、内核配置和编译
make x210ii_qt_defconfig make menuconfig make
3.1、先确认Makefile
(1)主要是检测交叉编译工具链有没有设置对。CROSS_COMPILE?=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
(2)确认ARCH=arm。主要目的是为了编译时能找到arch/arm目录。
3.2、makex210ii_qt_defconfig
(1)最后只要出现:configurationwrittento.config这句话,就证明我们的操作是正确的。若果没有出现这句话,就有错误。
(1)可能出现的错误1:名子敲错了。名子是字符串匹配的,一定要正确。
注意:假如这一步配置没有得到.config文件,是不能进行到下一步的。实际测试时没有.config也可以makemenuconfig,而且这样做下来的内核编译和烧录运行应当是有问题的。
3.3、makemenuconfig
(1)可能出现的错误1:ncurses库没装
错误信息:
***Unabletofindthencurseslibrariesorthe
***requiredheaderfiles.
***'makemenuconfig'requiresthencurseslibraries.
***
***Installncurses(ncurses-devel)andtryagain.
解决方案:apt-getinstalllibncurses5-dev(参考了:)
(2)可能出现的错误2:屏幕太小
错误信息:
YourdisplayistoosmalltorunMenuconfig!
Itmustbeatleast19linesby80columns.
解决方案:全屏,或则是把字体调小。
总结:makemenuconfig是第二步配置,具体的用法和配置意义在前面课程讲。我们这儿由于是九鼎早已移植过的,所以第二步配置是可以不做的,直接退出即可。
用鼠标的往右方向键联通到EXIT,按回车退出。
3.3、make
(1)可能出现的错误1:莫名其妙的错误,可以试试先makedistclean
(2)代码本身的错误:具体问题具体剖析
(3)编译完成后得到的内核镜像不在源码树的根目录下,在arch/arm/boot这个目录下。得到的镜像名是zImage
4、内核的配置原理
4.1、配置的关键是得到.config文件
(1).config以.开头,是一个隐藏文件,因而平常是看不到的,须要ls-a来看
(2)当我们makedistclean后(也就是说默认情况下)是没有.config文件的,我们配置的两步过程就是为了得到内容合适的.config文件
(3).config文件是linux内核在编译过程中很重要的一个文件,其作用类似与uboot中的include/configs/x210_sd.h,内核在编译过程中会读取.config中的配置项,但是用这种配置项去指导整个编译链接过程。
(4).config文件的格式类似于脚本文件,其中内容为类似于于:CONFIG_ARM=y的一个一个的配置项。这种配置项就类似于脚本文件中定义的一个一个变量,所以这一行可以被理解为定义了一个变量CONFIG_ARM,这个变量的值为y。
(5).config文件中每一行都是一个配置项,从.config文件的规模可以看出linux内核的可配置项有两三千个。所以linux内核是高度可配置的,但是linux内核的所有配置项很难全部搞明白。由于linux内核的配置项太多太冗长超出了人的脑部才能记忆和处理的数目级,因而linux内核不像uboot那样直接手工配置,而是发明了一个图形化的配置工具menuconfig。
4.2、makexx_defconfig和makemenuconfig相配合
(1)我们为了对.config文件中的两三千个配置项做逐一合适的配置,专门发明了两步结合的配置形式。
(2)虽然只要人的记忆足够好,脑部足够厉害,完全可以手工去书写/更改.config文件完成内核配置,最终只要.config中内容是正确的,就不影响编译过程。
(3)第一步:makexxx_defconfig解决的问题是大部份的配置项(这一步结束后99%的配置项就早已正确了),出来就是对某些不同的针对我们的开发板进行细节调整,细节调整就通过makemenuconfig来完成。
(4)makexxx_defconfig这一步当然是参考他人早已做好的,这样做有好多益处:降低好多工作量,避免了好多自己不懂的配置项(例如对显存管理的、调度系统的等模块的配置项),我们只用管自己须要管的。
(5)makemenuconfig似乎就是读取第一步得到的.config,之后给我们一个图形化的界面,让我们可以愈发容易的找到自己想要更改的配置项,之后修改配置他。
4.3、makexx_defconfig究竟做了哪些?
(1)makex210ii_qt_defconfig似乎相当于:cparch/arm/configs/x210ii_qt_defconfig.config
(2)arch/arm/configs目录下的那么多个xxx_defconfig那里来的?虽然这种文件都是他人手工配置好适宜一定的开发板的.config文件后自己把.config文件保存过去的。比如说我们用S55PVPV210这个SoC,针对这个SoC的开发板的最初配置肯定是三星的工程师去做的。
5、menuconfig解读
5.1、menuconfig本身由一套软件支持
(1)linux为了实现图形化界面的配置,专门提供了一套配置工具menuconfig。
(2)ncurses库是linux中拿来实现文字式的图形界面,linux内核中使用了ncurses库来提供menuconfig
(3)scriptskconfiglxdialog目录下的一些c文件就是拿来提供menuconfig的这些程序源代码。
5.2、menuconfig读取Kconfig文件
(1)menuconfig本身的软件只负责提供menuconfig工作的这一套逻辑(比如在menuconfig中通过上下左右箭头按钮来调整光标,EnterESC键等按钮按下的响应),而并不负责提供内容(菜单里的项目)。
(2)menuconfig显示的菜单内容(一方面是菜单的目录结构,另一方面是每一个菜单项目的细节)是由内核源码树各个目录下的Kconfig文件来支持的。Kconfig文件中根据一定的格式包含了一个又一个的配置项,每一个配置项在makemenuconfig中就会成为一个菜单项目。并且menuconfig中显示的菜单目录结构和源码目录中的Kconfig的目录结构是一样的。
(3)在相应的Kconfig文件中删掉一个config项,则再度makemenuconfig时这个项目早已看不到了。
5.3、menuconfig读取/写入.config文件
(1)刚刚早已晓得menuconfig的菜单内容来自于Kconfig文件,而且每一个菜单的选择结果(Y、N、M)却不是保存在Kconfig文件中的。Kconfig文件是不变的,Kconfig文件只是决定有没有这个菜单项,并不管这个菜单项的选择结果。
(2)menuconfig工作时在我们makemenuconfig打开时,他会读取.config文件,而且用.config文件中的配置选择结果来初始化menuconfig中各个菜单项的选择值。
总结:菜单项的项目内容从Kconfig文件来,菜单项的选择值从.config文件来
(3)当我们每次退出makemenuconfig时linux命令tar,menuconfig机制会首先检测我们有没有修改个别配置项的值linux 内核配置文件,假如我们本次没有更改过任意一个配置项目的值那直接退出;假如我们有改动配置项的值则会提示我们是否保存。此时若果点保存,则会将我们更改过的配置重新写入.config文件中记录,下一次再度打开makemenuconfig时会再度加载.config,最终去编译内核时编译联接程序会考虑.config中的配置值指导整个编译联接过程。
6、Kconfig文件解读
6.1、Kconfig的格式
(1)Kconfig根据一定的格式来书写,menuconfig程序可以辨识这些格式,之后从中提取出有效信息组成menuconfig中的菜单项。
(2)将来在做驱动移植等工作时,有时须要自己添加Kconfig中的一个配置项来将某个设备驱动添加到内核的配置项目中,这时侯就须要对Kconfig的配置项格式有所了解,否则就不会添加。
(3)#开头的行是注释行
(4)menuconfig表示菜单(本身属于一个菜单中的项目,而且他又有子菜单项目)、config表示菜单中的一个配置项(本身并没有子菜单下的项目)。
(5)menuconfig或则config前面空格隔开的小写字母表示的类似于NETDEVICES的就是这个配置项的配置项名子,这个字符串上面添加CONFIG_后就构成了.config中的配置项名子。
(6)一个menuconfig前面跟随的所有config项就是这个menuconfig的子菜单。这就是Kconfig中表示的目录关系。
(7)内核源码目录树中每一个Kconfig就会source引入其所有子目录下的Kconfig,因而保证了所有的Kconfig项目都被包含进menuconfig中。这个也告诉我们:假如你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,之后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。
6.2、tristate和bool的含意
(1)tristate意思是三态(3种状态,对应Y、N、M三种选择方法),bool是要么真要么假(对应Y和N)。所以tristate的意思就是这个配置项可以被三种选择,bool的意思是这个配置项只能被2种选择。
6.3、depends的含意
(1)depends英文意思是“取决于”或者“依赖于”,所以depends在这儿的意思是:本配置项依赖于另一个配置项。假如那种依赖的配置项为Y或则M,则本配置项才有意义;假如依赖的那个配置项本身被设置为N,则本配置项根本没有意义。
(2)depends项目会造成makemenuconfig的时侯找不到一些配置项。所以你在menuconfig中若果找不到一个选项,并且这个选项在Kconfig中却是有的,则可能的诱因就是这个配置项依赖的一个配置项是不创立的。
(3)depends并不要求依赖的配置项一定是一个,可以是多个,但是还可以有逻辑运算。这些时侯只要依赖项目运算多项式的裸机结果为真则依赖就组建。
6.4、help
(1)帮助信息,告诉我们这个配置项的含意,以及怎样去配置他。
6.5、Kconfig和.config文件和Makefile两者的关联
(1)配置项被配置成Y、N、M会影响.config文件中的CONFIG_XXX变量的配置值。
(2)这个.config中的配置值(=y、=m、没有)会影响最终的编译链接过程。假如=y则会被编入(built-in),倘若=m会被单独联接成一个ko模块,假如没有则对应的代码不会被编译。这么如此是如何实现的?都是通过makefile实现的。
(3)obj-$(CONFIG_DM9000)+=dm9000.o
假如CONFIG_DM9000变量值为y,则obj+=dm9000.o,因而dm9000.c会被编译;假如CONFIG_DM9000变量未定义,则dm9000.c不会被编译。假如CONFIG_DM9000变量的值为m则会被联接成ko模块(这个是在linux内核的Makefile中定义的规则)
总结:把menuconfig中的菜单项、Kconfig中的配置项、.config中的一行、Makefile中的一行,这4个东西结合上去理解,则整个linux内核的配置体系就明了了。
menuconfig用法翻译:
箭头按钮导航整个菜单,回车键盘选择子菜单(注意选项旁边有--->的选项才是有子菜单的,没有这个标示的没有子菜单),高亮的字母是键位(快捷键),鼠标键盘Y、N、M三个按钮的作用分别是将选中模块编入、去除、模块化。双击ESC表示退出,按下?键盘可以显示帮助信息,按下/键盘可以输入搜索内容来全局搜索信息(类似于vi中的搜索),[]不可以模块化,的才可以模块化。
注:linux内核中一个功能模块有三种编译方式:一种是编入、一种去消除、一种是模块化。所谓编入就是将这个模块的代码直接编译联接到zImage中去,消除就是将这个模块不编译链接到zImage中,模块化是将这个模块依然编译,而且不会将其链接到zImage中,会将这个模块单独链接成一个内核模块.ko文件,将来linux系统内核启动上去后可以动态的加载或卸载这个模块。
在menuconfig中选项上面的括弧里,*表示编入,空白表示清除,M表示模块化