一、kernel目录架构
linux内核是一个庞大的开源软件,针对arm,x86,mipi等等架构,内有不同平台的驱动代码,和与不同架构soc相关的核心代码
他们是如何进行编译的?
如下,输入 make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- uImage,可知,针对的是arm架构的,那么只会选择arm
架构的代码进行编译,那么顶层Makefile,Kconfig,.config,子目录kconfig,Makefile,kbuild,到底是如何知道完成编译的呢?
记录一下自己理解。
可以在网站直接浏览。
或下载一份kernel 源代码,目录如下。
s5pvx210开发板,三星提供的源码
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里面运行的叫固件。就像S5PV210里的iROM代码。
(7)fs。fs就是file system,文件系统,里面列出了linux支持的各种文件系统的实现。
(8)include。头文件目录,公共的(各种CPU架构共用的)头文件都在这里。每种CPU架构特有的一些头文件在arch/arm/include目录及其子目录下。
(9)init。init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码。
(10)ipc。ipc就是inter process commuication,进程间通信,里面都是linux支持的IPC的代码实现。
(11)kernel。kernel就是内核,就是linux内核,所以这个文件夹下放的就是内核本身需要的一些代码文件。
(12)lib。lib是库的意思,这里面都是一些公用的有用的库函数,注意这里的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数,这里的lib目录下的库函数就是用来替代那些标准库函数的。譬如在内核中要把字符串转成数字用atoi,但是内核编程中只能用lib目录下的atoi函数,不能用标准C语言库中的atoi。譬如在内核中要打印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的。
(13)mm。mm是memory management,内存管理,linux的内存管理代码都在这里。
(14)net。该目录下是网络相关的代码,譬如TCP/IP协议栈等都在这里。
(15)scripts。脚本,这个目录下全部是脚本文件,这些脚本文件不是linux内核工作时使用的,而是用来辅助对linux内核进行配置编译生产的。我们并不会详细进入分析这个目录下的脚本,而是通过外围来重点学会配置和编译linux内核即可。
(16)security。安全相关的代码。不用去管。
(17)sound。音频处理相关的。
(18)tools。linux中用到的一些有用工具
(19)usr。目录下是initramfs相关的,和linux内核的启动有关,暂时不用去管。
(20)virt。内核虚拟机相关的,暂时不用管。
总结:这么多目录跟我们关系很紧密的就是arch和drivers目录,然后其他有点相关的还有include、block、mm、net、lib等目录。
三星移植的目录
1、Makefile,kconfig,kbuild
主目录下或根目录下,想要编译它,是通过顶层makefile,kconfig,来组织的,主kconfig一个主菜单,指导哪些文件可以编译,我们选中哪些功能,就编译哪些功能进入系统。kconfig的内容如下,
会根据我们选中的arch结构,比如arm,x86,选中一种SOC来编译。 当输入make ARCH=arm,上面的srcarch会被赋值arm,就会选中
arch/arm下的kconfig。
进入arm目录下,看到有一个kconfig文件,这就是make menuconfig 配置菜单时,真正执行的文件,会跟据树根下的选项显示到主菜单上,
主kconfig里,有很多主菜单选项,后面每一个主选项,会有子选项,犹如树干,有很多树杈,如下语句,执行树杈子目录的kconfig,加载选项到子菜单显示。如果我们要添加一种文件,比如sound音频驱动就在主目录下,也是在这个kconfig下,加入sound相关的kconfig。
在kernel主根目录下,输入make menuconfig命令,出来如下面主菜单界面。
选中我们需要的soc,如三星的s5pv210,hisi的soc,和其他和cpu核心代码相关的代码,这些是设计cpu的厂家,如华为,三星做的事,外部人配置是很麻烦的事,因为很多不开放,我熟悉的代码,只有他们才知道,当他们配置好后,会保存配置到.congfig文件,在内核主根目录下,ls -a命令,可以看到这个文件,这个就是soc厂家配置好的,发布内核时,给我们的,我们一般在此基础上开发我们自己需要的驱动。
官网的kernel一般不会有.config文件,需要我们自己复制一份。或者厂家给我们的代码里有。进入arch/arm/configs目录下,
官方一般很少,厂家给我们时,会有很多配置好的不同soc的,不同领域的,不一样,比如我以前在海思做自动驾驶,就有很多config文件,和kbuild,做音视频的,又不一样,因为不同组做的,起的名字不一样,功能也不一样。
找一个hisi3520的默认config,把它拷贝出来到.config。
cp arch/arm/configs/hi3521d_full_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- menuconfig
2、子kconfig
举一个例子,进入driver里,kconfig里,会去执行子kconfig,加载各个模块的配置。
3、主Makefile
Makefile出厂了,上面配置好后,当输入make命令后,会根据规则去编译某某目录下的文件,如果有配置宏,会根据.config的配置判读是否需要编译为ko,还是直接编译进内核。
下面是直接把核心core直接编译。
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
vmlinux-dirs :=
(
p
a
t
s
u
b
s
t
(patsubst %/,%,
(patsubst(filter %/, $(init-y) $(init-m)
$(core-y) $(core-m) $(drivers-y) $(drivers-m)
$(net-y) $(net-m) $(libs-y) $(libs-m)))
vmlinux-alldirs := $(sort $(vmlinux-dirs)
(
p
a
t
s
u
b
s
t
(patsubst %/,%,
(patsubst(filter %/,
$(init-) $(core-) $(drivers-) $(net-) $(libs-))))
init-y := $(patsubst %/, %/built-in.o, $(init-y))
core-y := $(patsubst %/, %/built-in.o, $(core-y))
drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))
net-y := $(patsubst %/, %/built-in.o, $(net-y))
libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)
4、子Makefile
举一个例子,进入driver里,Makefile,编写了编译规则,根据.config配置,选择是否需要编进系统。
5、kbuild
后面再说吧,这个很重要,还有Makefile里,很多cflag,如何传参。还有如何开发驱动时,添加kconfig,
三,移植配置三星开发板记录
2.15.3.内核配置和编译体验
2.15.3.1、先确认Makefile
(1)主要是检查交叉编译工具链有没有设置对。CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
(2)确认ARCH = arm。主要目的是为了编译时能找到arch/arm目录。
2.15.3.2、make x210ii_qt_defconfig
(1)最后只要出现:configuration written to .config这句话,就证明我们的操作是正确的。如果没有出现这句话,就有错误。
(1)可能出现的错误1:名字敲错了。名字是字符串匹配的,一定要正确。
注意:如果这一步配置没有得到.config文件,是不能进行到下一步的。实际测试时没有.config也可以make menuconfig,但是这样做出来的内核编译和烧写运行应该是有问题的。
2.15.3.2、make menuconfig
(1)可能出现的错误1:ncurses库没装
错误信息:
*** Unable to find the ncurses libraries or the
*** required header files.
*** ‘make menuconfig’ requires the ncurses libraries.
*** Install ncurses (ncurses-devel) and try again.
解决方案: apt-get install libncurses5-dev (参考了:http://blog.csdn.net/yao_qinwei/article/details/8805101)
(2)可能出现的错误2:屏幕太小
错误信息:
Your display is too small to run Menuconfig!
It must be at least 19 lines by 80 columns.
解决方案:全屏,或者是把字体调小。
总结:make menuconfig是第二步配置,具体的用法和配置意义在后面课程讲。我们这里因为是九鼎已经移植过的,所以第二步配置是可以不做的,直接退出即可。
用键盘的向右方向键移动到EXIT,按回车退出。
2.15.3.3、make
(1)可能出现的错误1:莫名其妙的错误,可以试试先make distclean
(2)代码本身的错误:具体问题具体分析
(3)编译完成后得到的内核镜像不在源码树的根目录下,在arch/arm/boot这个目录下。得到的镜像名是zImage
记录如下
有了.config,才能继续make menuconfig,才能读取.config的配置,make menuconfig
安装menuconfig
例如配置dm9000网卡
kconfig结构
子菜单
菜单选项
配置uboot,