内核启动分析之Makefile

本文解析了Linux内核的Makefile结构及其编译过程,包括顶层、架构级及子目录下的Makefile如何协同工作,重点介绍了uImage的构建过程与依赖关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux内核的Makefile文件分类:

1.顶层的Makefile
2..config         所有的Makefile都是由.config来决定使用那些文件。
3.arch下的Makefile
4.script下的Makefile
5.kbuild Makefile  各级子目录下的Makefile。
在linux-2.6.22.6\Documentation\kbuild目录下的makefiles.txt对内核的Makefile讲的比较清楚,可以细看。
 在子目录下,如果有a.c b.c 两个模块要编译成模块可以这么做
obj-m += ab.o
ab-objs := a.o b.o
我们要分析Makefile从顶层的Makefile往下分析:
我们在编译内核的时候make uImage命令,那么uImage 的目标是位于哪里呢,我们的架构是arch/arm架构的,在这个目录下的Makefile可以找到他。
那我们在make uImage的时候,顶层目录下并没有找到uImage,那它是怎么做到make uImage的呢?
根据我们对Makefile的了解,那arch/arm架构的的Makefile可以被包含到顶层目录下的Makefile下,在顶层的Makefile下查找include我们可以找到:
# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
include $(srctree)/arch/$(ARCH)/Makefile
可以看出它是被包含到顶层的Makefile了。
对于.config 会生成autoconf.h、auto.conf,他是不是也被包含进顶层的Makefile了呢,查一下auto.conf。
# Read in config
-include include/config/auto.conf

可以看到也是包含进来了。

zImage Image xipImage bootpImage uImage: vmlinux

uImage的依赖是vmlinux,我们在架构下的Makefile下并没有找到vmlinux的依赖,在顶层的Makefile下找到了vmlinux的依赖:

# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE

那vmlinux-lds、vmlinux-main、vmlinux-init这些分别是什么呢,我们可以在顶层的Makefile下查查:

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

#Default value
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o  //在架构下的Makefile定义的。

init-y := init/

init-y := $(patsubst %/, %/built-in.o, $(init-y))               //在顶层的Makefile下定义的。

$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”中以.c结尾的单词替换成以.o结尾的字符。函数的返回结果是“x.c.o bar.o”

展开为:init-y := init/build-in.o 

vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)

core-y := usr/

core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

core-y := $(patsubst %/, %/built-in.o, $(core-y))

展开为:core-y   :=usr/build-in.o kernel/build-in.o mm/build-in.o fs/build-in.o  security/build-in.o crypto/build-in.o block/build-in.o 

libs-y := lib/

libs-y1 := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y := $(libs-y1) $(libs-y2)

展开为libs-y := lib/build-in.o lib/lib.a

drivers-y := drivers/ sound/

drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y))

展开为drivers-y := drivers/build-in.o sound/build-in.o

net-y := net/

net-y := $(patsubst %/, %/built-in.o, $(net-y))

vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds

前面分析的一堆原材料是怎么被链接到一起的呢?

# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
ifdef CONFIG_HEADERS_CHECK
$(Q)$(MAKE) -f $(srctree)/Makefile headers_check
endif
$(call if_changed_rule,vmlinux__)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
$(Q)rm -f .old_version

这要分析Makefile的话比较庞大了,只是想了解它的话我们编译一下内核看结果。

要是我们之前编译过内核的话我们先rm 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

截取一段,我们可以看到这些跟我们之前分析的很对应,待会我们在看下他的链接脚本。

从上面的分析中我们可以得到一些比较中要的信息:

1.第一个文件:arch/arm/kenel/head.s

2.链接脚本:arch/arm/kernl/vmlinux.lds

不过在内核目录下找不到vmlinux.lds,该文件为vmlinux.lds.S生成。我们可以打来vmlinux.lds看看他的一些内容。

具体的不做分析了,内核大概的Makefile就这样有个基本的认识了。

SECTIONS
{
 . = (0xc0000000) + 0x00008000;
 .text.head : {
  _stext = .;
  _sinittext = .;
  *(.text.head)       //所有文件的段
 }
 .init : { /* Init code and data */
   *(.init.text)
  _einittext = .;
  __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;
  __arch_info_begin = .;
   *(.arch.info.init)
  __arch_info_end = .;
  __tagtable_begin = .;
   *(.taglist.init)
  __tagtable_end = .;
  . = ALIGN(16);
  __setup_start = .;

。。。。。。。。。。。。

。。。。。。。。。。。

。。。。。。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值