首先根据开发板的资料,在自己的开发环境中建立交叉编译环境,安装交叉编译工具链。
厂家提供的内核源码拷贝到开发机中,解压并进入到主路径:
tar -xvzf linux-2.6.28.6-20111212.tar.gz
cd linux-2.6.28.6/
zdy@ubuntu:~/work/linux-2.6.28.6$ ls -alh
total 1020K
drwxr-xr-x 22 zdy zdy 4.0K Dec 12 2011 .
drwxrwxr-x 6 zdy zdy 4.0K Apr 2 19:58 ..
drwxr-xr-x 24 zdy zdy 4.0K Dec 8 2009 arch
drwxr-xr-x 2 zdy zdy 4.0K Dec 12 2011 block
-rw-r--r-- 1 zdy zdy 67K Apr 30 2009 ChangeLog
-rw-r--r-- 1 zdy zdy 64K Apr 30 2009 ChangeLog_mfc
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_a70
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_ezvga
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_h43
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_l80
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_n43
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_s70
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_t35
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_vga1024x768
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_vga640x480
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_vga800x600
-rw-r--r-- 1 zdy zdy 42K Dec 12 2011 config_mini6410_w50
-rw-r--r-- 1 zdy zdy 19K Apr 30 2009 COPYING
-rw-r--r-- 1 zdy zdy 92K Apr 30 2009 CREDITS
-rw-r--r-- 1 zdy zdy 11 Apr 7 2010 .cross_compile
drwxr-xr-x 3 zdy zdy 4.0K Dec 12 2011 crypto
drwxr-xr-x 82 zdy zdy 4.0K May 27 2010 Documentation
drwxr-xr-x 83 zdy zdy 4.0K Dec 12 2011 drivers
drwxr-xr-x 18 zdy zdy 4.0K Dec 12 2011 firmware
drwxr-xr-x 63 zdy zdy 4.0K Dec 12 2011 fs
-rw-r--r-- 1 zdy zdy 867 Apr 30 2009 .gitignore
drwxr-xr-x 27 zdy zdy 4.0K Dec 12 2011 include
drwxr-xr-x 2 zdy zdy 4.0K Dec 12 2011 init
drwxr-xr-x 2 zdy zdy 4.0K Dec 12 2011 ipc
-rw-r--r-- 1 zdy zdy 2.4K Apr 30 2009 Kbuild
drwxr-xr-x 6 zdy zdy 4.0K Dec 12 2011 kernel
drwxr-xr-x 6 zdy zdy 4.0K Dec 12 2011 lib
-rw-r--r-- 1 zdy zdy 3.9K Apr 30 2009 .mailmap
-rw-r--r-- 1 zdy zdy 104K Apr 30 2009 MAINTAINERS
-rw-r--r-- 1 zdy zdy 57K Dec 11 2011 Makefile
drwxr-xr-x 2 zdy zdy 4.0K Dec 12 2011 mm
drwxr-xr-x 45 zdy zdy 4.0K Dec 12 2011 net
-rw-r--r-- 1 zdy zdy 17K Apr 30 2009 README
-rw-r--r-- 1 zdy zdy 3.1K Apr 30 2009 REPORTING-BUGS
drwxr-xr-x 7 zdy zdy 4.0K Apr 30 2009 samples
drwxr-xr-x 10 zdy zdy 4.0K Dec 12 2011 scripts
drwxr-xr-x 5 zdy zdy 4.0K Dec 12 2011 security
drwxr-xr-x 20 zdy zdy 4.0K Dec 12 2011 sound
drwxr-xr-x 2 zdy zdy 4.0K Dec 12 2011 usr
drwxr-xr-x 3 zdy zdy 4.0K Apr 30 2009 virt
上述内核压缩包解压出来后,会有好多文件,具体文件先关内容解释如下:
- arch:这个文件夹包含了一个Kconfig文件,它用于设置这个目录里的源代码编译所需的一系列设定。每个支持的处理器架构都在它相应的文件夹中。
- block: 此文件夹包含块设备驱动程序的代码,该目录用于实现块设备的基本框架和块设备的I/O调度算法。块设备是以数据块方式接收和发送的数据的设备。数据块都是一块一块的数据而不是持续的数据流。
- ChangeLog:内核的更改日志
- config_*: 厂家提供的一些列配置文件
- crypto: 这个文件夹包含许多加密算法的源代码.
- Documentation: 内核相关文档
- drivers: 设备驱动程序,各个不同的驱动占用一个子目录
- firmware: 包含让计算机读取和理解从设备发来的信号的代码
- fs: 文件系统相关的文件夹
- include: include包含了内核所需的各种头文件
- init:内核初始化代码,著名的start_kernel()就位于init/main.c文件中
- ipc:进程间通信的相关文件夹
- kernel:内核最核心的部分,包括进程调度,定时器等,和平台相关的一部分代码放在arch/*/kernel 下。
- lib:内核需要引用的一系列内核库文件代码
- Makefile: 内核编译顶部Makefile
- mm:内存管理文件夹
- net:网络控制文件夹
- samples: 此文件夹包含了程序示例和正在编写中的模块代码
- scripts: 内核编译所需的脚本
- security:有关内核安全的代码
- sound: 声卡驱动相关代码
- usr:为用户层在内核启动时添加支持
- virt: 虚拟化功能代码
- COPYING: 许可和授权信息
- CREDITS: 贡献者列表
- .cross_compile : 长阿基提供的交叉编译配置文件
- Kbuild:内核设定的脚本
首先根据厂家的指导书,我们先按照步骤进行配置
root@ubuntu:~/work/linux-2.6.28.6# cp config_mini6410_n43 .config
然后编译内核:
373 if (@val) {
374 @val = compute_values($hz);
375 }
make zImage V=1
当命令行编译时输入V=1时,可以清楚的看到每一条指令
编译过程中,可能由于版本问题,会出现如下错误:
Can’t use ‘defined(@array)’ (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.
解决方案是将kernel/timeconst.pl中第373行的defined()去掉只留下@val就可以了,如下:
sudo vim kernel/timeconst.pl
改为如下内容即可
373 if (@val) {
374 @val = compute_values($hz);
375 }
在此编译,此错误消失
编译时间因电脑而已,稍等就是。最后编译结果如下:
最终编译的内核镜像在arch/arm/boot/路径下
把 zImage 下载到开发板接口运行起来了。
以上是实操,至于其编译原理,还需要解析其Makefile文件
FriendlyARM mini6410内核Makefile解析-文本注释
以下解析都是个人看法,如果不对之处,还请大家告知:
-
编译配置
在编译内核时,通常需要先配置,本开发板采用厂家提供的配置文件来做配置,可以更改或者默认。.config即为顶层配置文件,可以通过控制命令行输入make menuconfig来生成或者修改。顶层Makefile会使用这个.config文件来构建内核。include/config/auto.conf 路径下会自动生成一个auto.conf文件,各级Makefile可通过此文件来确定编译内容。
其次,大多数内核软件模块也通过.config文件间接地读取配置内容,原理如下:
在构建过程中,构建系统会处理这个.config文件,并生成一个名为autoconf.h的C语言头文件,放在目录…/include/linux中,这个文件是自动生成的。尽量不要直接修改这个文件。
综上所述:配置过程主要是通过make menuconfig来完成编译配置,并生成.config文件。在编译过程中,会自动生成include/config/auto.conf 文件工Makefile调用以及include/linux/autoconfig.h功内核源码引用. -
编译内核
由用户层交互角度进行第二笔编译,通命令行make开始编译内核。根据Makefile规则,其默认规则是编译 make all,
根据上述四张图片及相关文件内容可知,编译目标文件为vmlinux、zImage及moudles -
编译vmlinux
根据Makefile可以得到 vmlinux 依赖文件为:
- (vmlinux-lds) arch/arm/kernel/vmlinux.lds
- (vmlinux-init) arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o
- (vmlinux-main) usr/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.a lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o net/built-in.o
- (vmlinux.o) 其依赖文件为:arch/arm/kernel/head.o arch/arm/kernel/init_task.o usr/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o lib/lib.a lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o net/built-in.o
- (kallsyms.o) .tmp_kallsyms2.o
上述依赖关系中仅仅是解析顶层Makefile中展开的的内容,子路径下的Makefile未做展开合入(顶层Makefile会include一些文件,其中也会添加一些依赖文件)
-
编译zImage
根据arch/arm/Makefile中编译规则,其依赖文件为vmlinux,具体如下:
此步骤编译输出如下所示:
make -f scripts/Makefile.build obj=arch/arm/boot MACHINE=arch/arm/mach-s3c6400/ arch/arm/boot/zImage
-
编译Modules
由顶层Makefile解析后可知:vmlinux-dirs = init, arch/arm/kernel, arch/arm/mm, arch/arm/common, arch/arm/net, arch/arm/crypto, arch/arm/firmware, arch/arm/mach-astevb, drivers, sound, firmware, net, lib, arch/arm/lib此步骤编译输出如下所示:
awk '!x[$0]++' /home/zdy/work/linux-2.6.28.6/init/modules.order /home/zdy/work/linux-2.6.28.6/usr/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/kernel/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/mm/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/common/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/mach-s3c6400/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/mach-s3c6410/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/plat-s3c64xx/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/plat-s3c/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/nwfpe/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/vfp/modules.order /home/zdy/work/linux-2.6.28.6/kernel/modules.order /home/zdy/work/linux-2.6.28.6/mm/modules.order /home/zdy/work/linux-2.6.28.6/fs/modules.order /home/zdy/work/linux-2.6.28.6/ipc/modules.order /home/zdy/work/linux-2.6.28.6/security/modules.order /home/zdy/work/linux-2.6.28.6/crypto/modules.order /home/zdy/work/linux-2.6.28.6/block/modules.order /home/zdy/work/linux-2.6.28.6/drivers/modules.order /home/zdy/work/linux-2.6.28.6/sound/modules.order /home/zdy/work/linux-2.6.28.6/firmware/modules.order /home/zdy/work/linux-2.6.28.6/net/modules.order /home/zdy/work/linux-2.6.28.6/arch/arm/lib/modules.order /home/zdy/work/linux-2.6.28.6/lib/modules.order > /home/zdy/work/linux-2.6.28.6/modules.order
Building modules, stage 2.
make -f /home/zdy/work/linux-2.6.28.6/scripts/Makefile.modpost
scripts/mod/modpost -o /home/zdy/work/linux-2.6.28.6/Module.symvers -S -c -s
arm-linux-gcc -Wp,-MD,drivers/char/.mini6410_hello_module.mod.o.d -nostdinc -isystem /home/zdy/work/opt/FriendlyARM/toolschain/4.5.1/bin/../lib/gcc/arm-none-linux-gnueabi/4.5.1/include -D__KERNEL__ -Iinclude -I/home/zdy/work/linux-2.6.28.6/arch/arm/include -include include/linux/autoconf.h -mlittle-endian -Iarch/arm/mach-s3c6400/include -Iarch/arm/mach-s3c6410/include -Iarch/arm/plat-s3c64xx/include -Iarch/arm/plat-s3c/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -D__LINUX_ARM_ARCH__=6 -march=armv6k -mtune=arm1136j-s -msoft-float -Uarm -Wframe-larger-than=1024 -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wno-pointer-sign -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(mini6410_hello_module.mod)" -D"KBUILD_MODNAME=KBUILD_STR(mini6410_hello_module)" -DMODULE -c -o drivers/char/mini6410_hello_module.mod.o drivers/char/mini6410_hello_module.mod.c
arm-linux-ld -EL -r -o drivers/char/mini6410_hello_module.ko drivers/char/mini6410_hello_module.o drivers/char/mini6410_hello_module.mod.o
arm-linux-gcc -Wp,-MD,drivers/scsi/.scsi_wait_scan.mod.o.d -nostdinc -isystem /home/zdy/work/opt/FriendlyARM/toolschain/4.5.1/bin/../lib/gcc/arm-none-linux-gnueabi/4.5.1/include -D__KERNEL__ -Iinclude -I/home/zdy/work/linux-2.6.28.6/arch/arm/include -include include/linux/autoconf.h -mlittle-endian -Iarch/arm/mach-s3c6400/include -Iarch/arm/mach-s3c6410/include -Iarch/arm/plat-s3c64xx/include -Iarch/arm/plat-s3c/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Os -marm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -D__LINUX_ARM_ARCH__=6 -march=armv6k -mtune=arm1136j-s -msoft-float -Uarm -Wframe-larger-than=1024 -fno-stack-protector -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wno-pointer-sign -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(scsi_wait_scan.mod)" -D"KBUILD_MODNAME=KBUILD_STR(scsi_wait_scan)" -DMODULE -c -o drivers/scsi/scsi_wait_scan.mod.o drivers/scsi/scsi_wait_scan.mod.c
arm-linux-ld -EL -r -o drivers/scsi/scsi_wait_scan.ko drivers/scsi/scsi_wait_scan.o drivers/scsi/scsi_wait_scan.mod.o
make -f /home/zdy/work/linux-2.6.28.6/scripts/Makefile.fwinst obj=firmware __fw_modbuild
如下是内核编译终端输出日志
FriendlyARM mini6410内核编译输出日志
综上分析,内核编译主要工作是在编译vmlinux,该文件也是各个镜像文件的依赖文件。编译此文件时,会逐级展开内核各文件夹下的子Makefile并编译各种文件,最终生成vmlinux文件。