1_5.3.3_内核配置裁剪及启动流程_内核启动流程分析之Makefile_P

分析Makefile,主要是:

  1. 找到第1个文件,从这个文件入手分析启动流程;
  2. 链接脚本,分析文件分布情况。

涉及的文件分类如下:

在这里插入图片描述

kbuild Makefile

首先来看子目录下面的Makefile,也就是kbuild Makefile,每个子目录下面都会有一个Makefile,它们的主要功能是设置该目录的文件的编译选项。

选取一个子目录下的Makefile来研究一下。
在这里插入图片描述

其中大部分的内容是设置文件的编译选项。
在这里插入图片描述

假设有两个文件a.c和b.c,如果需要单独的将它们编译进内核,可以使用如下语句:

obj-y += a.o b.o

那么,如果要将这两个文件编成一个模块呢?

在内核的Document/kbuild目录下有一个makefile.txt文件,查看makefile.txt,可以发现下图描述。
在这里插入图片描述

内核需要知道你想要生成的模块由哪些文件组成,因此你需要通过一个$(<module_name>-objs)变量来告诉内核。

在这个例子中,模块名字叫做isdn.o。Kbuild会编译 $ (isdn-objs)变量中的文件,然后对这些文件使用"$(LD) -r"来生成isdn.o。

也就是说,如果要将a.c和b.c编成一个模块,那么需要使用如下指令:

obj-y += ab.o(这个名字不重要)
ab-objs := a.o b.o

另外,使用后缀-y也是可以的,指令如下:

obj-y += ab.o(这个名字不重要)
ab-y := a.o b.o

makefiles.txt中还提到,如果需要在编译时再决定一个文件是否加入这个模块,也是可以实现的。具体实现如上图的第二个例子所描述。(如果不想编入内核,只是变成一个动态库,那么-y参数就替换为-m即可,生成的模块类型则是.ko类型)

子目录下的Makefile就先理解到这里,规则先不看,接下来是架构相关的Makefile(arch/ $(ARCH)/Makefile)。

arch/ $(ARCH)/Makefile

架构相关的Makefile主要决定哪些体系结构相关的文件参与内核的生成,并提供一些规则来生成特定格式的内核映像。

查看一下arch/arm目录下的Makefile。
在这里插入图片描述

编译内核时,我们使用make或者make uImage指令,直接从指令分析入手,就不单独看这个Makefile了,不然思路不够清晰。

根据make uImage分析Makefile,在arch/arm目录下找到uImage(2440是arm架构,使用的arch/arm目录下的Makefile,如果是其他架构,则使用对应架构下的Makefile)。
在这里插入图片描述
在这里插入图片描述
可以看到,uImage的编译依赖于vmlinux,再查找vmlinux,在顶层Makefile找到了它的依赖关系。
在这里插入图片描述
暂时知道arch/arm/的Makefile是被包含到顶层Makefile,先来看一下.config。

.config

之前分析的时候说过,.config文件会生成autoconf.h和auto.conf文件,查找顶层Makefile,可以看到这两个文件也被包含进来了。
在这里插入图片描述
在这里插入图片描述

打开.config,可以看到里面全部都是这样的定义语句,表示的意思就不赘述了,之前已经有详细的说明了。
在这里插入图片描述

顶层Makefile

还是以指令make uImage来分析,根据上面的分析,可以知道uImage依赖于vmlinux,vmlinux又依赖于 $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE。

从名字可以看出,init应该是初始化相关,lds应该是链接,main应该是主函数。
在这里插入图片描述

我们前面分析uImage的时候知道,uImage是由 “头部(64字节)+真正的内核”组成的,其中真正的内核就是vmlinux。

查找vmlinux-init,得到如下信息。

在这里插入图片描述
对于vmlinux-init的分析如下:

vmlinux-init := $(head-y) $(init-y)

head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
在这里插入图片描述

其中,$(MMUEXT)在arch/arm/Makefile前面定义,对于没有MMU的处理器,MMUEXT的值为-nommu,使用文件head-nommu.S;对于有MMU的处理器,其值为空,使用head.S文件。
在这里插入图片描述

所以:head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o

还有一个$(init-y)。

init-y := init/
在这里插入图片描述

init-y := $ (patsubst %/, %/built-in.o, $(init-y)),其中, $(patsubst 原模式, 目标模式, 文件列表)。

在这里插入图片描述

所以,init-y := init/t/built-in.o,它的意思是所有init文件夹下的目标文件会被编程进一个模块叫build-in.o

综上,vmlinux-init := arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o

在这里插入图片描述然后是vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y),从名字分析,分别是核心,库,驱动,网络。

查找core-y,得:

core-y := usr/
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
// If we have a machine-specific directory, then include it in the build.
core-y += $(MACHINE)
core-y := $(patsubst %/, %/built-in.o, $(core-y))

也就是:core-y := usr/ kernel/ mm/ fs/ ipc/ security/ crypto/ block/ arch/arm/kernel/ arch/arm/mm/ arch/arm/common/,然后和上面一样生成各个文件夹的built-in.o,也就是将各个目录下的目标文件一起编译成一个模块。

其他 $(libs-y) $(drivers-y) $(net-y) 也是类似的操作。

最后是链接脚本,vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds,其中ARCH表示的是MCU架构,所以ARCH = arm,也就是:

vmlinux-lds := arch/arm/kernel/vmlinux.lds

打开arch/arm/kernel/vmlinux.lds,可以看到,其中开始的地址应该是一个虚拟地址,存放的是所有文件的head段,然后是初始化相关的代码段。顺序由链接时出现的文件顺序来决定。
在这里插入图片描述
直接查看编译信息可以更方便的了解这些信息,rm vmlinux先删除vmlinux,然后再make uImage V=1编译,V=1会将调试信息更详细的打印出来。

arm-linux-ld -EL -p --no-undefined -X -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/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 arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o
echo ‘cmd_vmlinux := arm-linux-ld -EL -p --no-undefined -X -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/mach-s3c2410/built-in.o arch/arm/mach-s3c2400/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/mach-s3c2442/built-in.o arch/arm/mach-s3c2443/built-in.o arch/arm/nwfpe/built-in.o arch/arm/plat-s3c24xx/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 arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o’ > ./.vmlinux.cmd

在这里插入图片描述
通过编译信息,可以知道,使用的链接脚本是arch/arm/kernel/vmlinux.lds(由arch/arm/kernel/vmlinux.lds.S编译生成),第一个文件应该是一个汇编文件head.S,文件顺序与之前分析的vmlinux-init := arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o也相同。

所以,我们知道了:

  1. 找到第1个文件,从这个文件入手分析启动流程;(arch/arm/kernel/head.S)
  2. 链接脚本,分析文件分布情况。(arch/arm/kernel/vmlinux.lds)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值