主Makefile分析:
- 刚开始定义了kernel的版本号
- make 编译内核时,也可以通过make O=…传参(和uboot一样)指定编译目录
- 两个重要的变量 ARCH,CROSS_COMPILE决定了架构和编译工具链路径,这两个参数也可以通过make时传参
例:
make O=/tmp/mykernel ARCH=arm CROSS_COMPILE=/usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
链接脚本分析:
- 找到整个程序的入口
ENTRY(stext)
stext 在 arch/arm/kernel/目录下的head.S中
- kernel的连接脚本并不是直接提供的,而是提供了一个汇编文件vmlinux.lds.S,然后在编译的时候再去编译这个汇编文件得到真正的链接脚本vmlinux.lds,因为链接脚本不能使用条件编译,所以使用汇编文件进行条件编译,然后生成链接脚本
head.S文件:
1. 内核运行的物理地址和虚拟地址
#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #0xC0008000
#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) #0x30008000
这里内核运行的物理地址是0x30008000,对应的虚拟地址是0xC0008000
2. 内核的真正入口
__HEAD
ENTRY(stext)
__HEAD定义了后面的代码属于段名为.head.text段
3. 内核运行的条件
(1)内核的起始部分代码是被解压代码调用的。,解压代码运行时先将zImage后段的内核解压开,然后再去调用运行真正的内核入口。
(2)内核启动不是无条件的,而是有一定的先决条件,这个条件由启动内核的bootloader来构建保证。
(3)ARM体系中,函数调用时实际是通过寄存器传参的(函数调用时传参有两种设计:一种是寄存器传参,另一种是栈内存传参)。所以uboot中最后theKernel (0, machid, bd->bi_boot_params);执行内核时,运行时实际把0放入r0中