第3阶段——内核启动分析之make uImage编译内核(3)
目标:
通过分析makefile,明白make uImage如何编译内核
把整个内核的makefile分成三类(makefile资料文档在linux-2.6.22.6/Documentation/build/makefiles.txt)
<1>各级子目录makefile(每个子目录都有makefile)
<2>/arch/arm/Makefile(架构相关的makefile)
<3>顶层目录makefile
在顶层目录makefile中auto.conf和/arch/arm/Makefile又被包含在其中,如下所示:
include $(srctree)/arch/$(SRCARCH)/Makefile 443 include include/config/auto.conf
1.分析子目录makefile, 随便打开一个子目录makefile,可以看到类似的内容:
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o obj-m += s3c24xx_leds.o obj-m += s3c24xx_buttons.o obj-m += ker_rw.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o
在makefile资料文档中得到(linux-2.6.22.6/Documentation/build/makefiles.txt)
--- 3.2 Built-in object goals - obj-y ~ .... Example: #drivers/isdn/i4l/Makefile # Makefile for the kernel ISDN subsystem and device drivers. # Each configuration option enables a list of files. obj-$(CONFIG_ISDN) += isdn.o obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
从上面第40行得出要追加built-in.o文件(编译进内核)时,使用obj-y
例如: obj-y += isdn.o
obj-y+= isdn_bsdcomp.o
--- 3.3 Loadable module goals - obj-m ~ ... Example: #drivers/isdn/i4l/Makefile obj-$(CONFIG_ISDN) += isdn.o isdn-objs := isdn_net_lib.o isdn_v110.o isdn_common.o
从上面第167行得出加载模块.ok文件时,使用obj-m
例如: obj-m += isdn.o
isdn-objs: = isdn_net_lib.o isdn_v110.o isdn_common.o
最后编译成isdn.ko模块文件
所以
在配置文件auto.conf中CONFIG_XXX=y, 那么编译时,源码.o文件会被Makefile追加到built-in.o文件,供给顶层Makefile生成内核
在配置文件auto.conf中CONFIG_XXX=m,那么编译时, 源码.o文件会被Makefile编译成模块XXX.ko文件;
在配置文件auto.conf中CONFIG_XXX=n, 那么编译时,对应的源码文件不会被makefile编译;
2分析./arch/arm/Makefile(ARM架构makefile)
首先在./arch/arm/Makefile文件第227行得到:
zImage Image xipImage bootpImage uImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
得出uImage等5个目标的生成都是依赖于vmlinux(vmlinux位于顶层makefile,其中vmlinux 指未压缩的内核,不能直接加载)
由于,我们在顶层目录下执行make uImage,但是uImage在./arch/arm/Makefile,
在顶层makefile中第413行可以看到:
include $(srctree)/arch/$(SRCARCH)/Makefile
由于打上补丁后, SRCARCH=arm
所以这个./arch/arm/Makefile被顶层makefile包含,然后调用了./arch/arm/Makefile中的uImage
3 分析顶层目录Makefile
3.1 顶层vmlinux生成过程
在顶层目录makefile中第484行得出:
all: vmlinux
其中,all就是直接 make 指令编译内核,显然make uImage和make都依赖于vmlinux(内核)
然后在746得到出vmlinux生成步骤:
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
3.1.1 接下来分析顶层vmlinux依赖文件
可以看出vmlinux依赖于:
vmlinux-lds: 链接脚本
vmlinux-init: 初始化相关的代码
vmlinux-main:核心代码
kallsyms.o: 变量
这些依赖在顶层Makefile中608行处定义:
vmlinux-init := $(head-y) $(init-y) // head-y:头文件 init-y:初始化文件
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) // core-y:核心文件libs-y:库文件 drivers-y:驱动文件net-y:网络文件
vmlinux-lds := arch/$(SRCARCH)/kernel/vmlinux.lds // arch/arm/kernel/vmlinux.lds链接脚本
逐个分析:
(1) vmlinux-lds
因为我们是使用的arm架构,$(SRCARCH) = arm
因此 vmlinux-lds :=arch/arm/kernel/vmlinux.lds
首先查看arch/arm/kernel/vmlinux.lds文件
如下所示,在288行处设置了内核运行在虚拟地址0Xc0008000处,接下来按顺序存放vmlinux的依赖文件
SECTIONS
{
. = (0xc0000000) + 0x00008000; //设置内核运行地址
.text.head : {
_stext = .;
_sinittext = .;
*(.text.head) //存放.text.head段
}
.init : {
*(.init.text) //存放.init.text段
... ...
(2) vmlinux-init
head-y在/arch/arm/makefile中94行处定义:
head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
由于MMUEXT没有定义 ,所以变量head-y 应为
head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
init-y在顶层makefile中427行中定义:
init-y := init/
然后在532行中修改init-y
init-y := $(patsubst %/, %/built-in.o, $(init-y))
这里的patsubst 是实现匹配替换的,在这里将$(init-y) 中的 / 替换为'/built-in.o' 。
所以变量init-y 应为
init-y := init/built-in.o
因此 vmlinux-init := arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o
(3) vmlinux-main
core-y 在顶层Makefile中438行定义,在562行处追加,在574行处修改:
core-y := usr/ core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ core-y := $(patsubst %/, %/built-in.o, $(core-y)) //将$(core-y)中的 的/ 替换为'/built-in.o' 。
所以变量core-y 应为
core-y := usr/ built-in.o kernel/ built-in.o mm/ fs/ built-in.o ipc/ built-in.o security/ built-in.o crypto/ built-in.o block/ built-in.o
libs-y 在顶层Makefile中437行定义,然后后面577行进行修改:
libs-y := lib/ libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) // libs-y1:= lib/ lib.a libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) // libs-y2:= lib/ built-in.o libs-y := $(libs-y1) $(libs-y2) // libs-y:= lib/ lib.a lib/ built-in.o
所以变量libs-y 应为
libs-y:= lib/ lib.a lib/ built-in.o
core-y 在顶层Makefile中435行定义,在574行处修改:
drivers-y := drivers/ sound/ drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)
所以变量drivers-y 应为
drivers-y := drivers/ built-in.o sound/ built-in.o
net-y 在顶层Makefile中436行定义,在575行处修改:
net-y := net/ net-y := $(patsubst %/, %/built-in.o, $(net-y))
所以变量net-y 应为
net-y := net/ built-in.o
因此 vmlinux-main := usr/ built-in.o kernel/ built-in.o mm/ 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
net/ built-in.o
vmlinux的依赖文件分析完毕
3.1.2 顶层vmlinux生成规则分析
直接make uImage ,然后ctrl+z 暂停编译,从串口上分析
(1)首先rm vmlinux 删除目标文件,再make uImage v=1 (V=1表示显示详细编译过程 )

如上图, 主要通过arm-linux-ld连接选项,通过vmlinux.lds链接脚本对内存的地址设置,然后将 顶层vmlinux依赖文件分析出来的所有文件按一定顺序布局并输出vmlinux文件 (arm-linux-ld使用参考:http://www.cnblogs.com/lifexy/p/7065175.html)
第3阶段——内核启动分析之make uImage编译内核(3)的更多相关文章
- mkimage工具 加载地址和入口地址 内核启动分析
第三章第二节 mkimage工具制作Linux内核的压缩镜像文件,需要使用到mkimage工具.mkimage这个工具位于u-boot-2013. 04中的tools目录下,它可以用来制作不压缩或者压 ...
- 第3阶段——内核启动分析之start_kernel初始化函数(5)
内核启动分析之start_kernel初始化函数(init/main.c) stext函数启动内核后,就开始进入start_kernel初始化各个函数, 下面只是浅尝辄止的描述一下函数的功能,很多函数 ...
- 第3阶段——内核启动分析之make menuconfig内核配置(2)
目标: 分析make menuconfig内核配置过程 在上1小结中(内核编译试验)讲到了3种不同的配置: (1)通过make menuconfig 直接从头到尾配置.config文件 (2) 通过m ...
- 第3阶段——内核启动分析之prepare_namespace()如何挂载根文件系统和mtd分区介绍(6)
内核启动并初始化后,最终目的是像Windows一样能启动应用程序,在windows中每个应用程序都存在C盘.D盘等,而linux中每个应用程序是存放在根文件系统里面,那么挂载根文件系统在哪里,怎么实现 ...
- 第3阶段——内核启动分析之创建si工程和分析stext启动内核函数(4)
目标: (1)创建Source Insight 工程,方便后面分析如何启动内核的 (2)分析uboot传递参数,链接脚本如何进入stext的 (3) 分析stext函数如何启动内核: (3.1) ...
- tms320dm6446内核启动分析
关于达芬奇DM6446,里面内部有两个部分,一个是ARM926ejs的核,还有一个是C64+DSP的视频处理核,而我需要关心的重点是arm926ejs的核(bootload和linux内核) 从boo ...
- Linux内核及分析 第三周 Linux内核的启动过程
实验过程: 打开shell终端,执行以下命令: cd LinuxKernel/ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootf ...
- linux-2.6.22.6内核启动分析之head.S引导段代码
学习目标: 了解arch/arm/kernel/head.S作为内核启动的第一个文件所实现的功能! 前面通过对内核Makefile的分析,可以知道arch/arm/kernel/head.S是内核启动 ...
- Linux内核启动分析过程-《Linux内核分析》week3作业
环境搭建 环境的搭建参考课件,主要就是编译内核源码和生成镜像 start_kernel 从start_kernel开始,才真正进入了Linux内核的启动过程.我们可以把start_kernel看做平时 ...
随机推荐
- 用vector实现dijkstra
#include <stdio.h> #include <string.h> #include <string> #include <vector> # ...
- hiberate关系映射大全
1. 集合映射 开发流程: 需求分析/数据库设计.项目设计/ 编码/测试/实施部署上线/验收 需求: 用户购买, 填写地址! 数据库: 代码: // javabean设计 public class U ...
- java自学找工作经历
断断续续的,折腾了7个多月,学完了在网上购买的培训机构J2EE的全套课程.期间各种蛋疼看另一篇博客 http://www.cnblogs.com/work396/p/6791488.html 直接说找 ...
- 阿里云ECS主机自定义进程监控
由于业务的关系我们用的是阿里云的ECS主机,需要对业务进程需要监控,查看后发现阿里云提供自定义监控SDK,这有助于我们定制化的根据自身业务来做监控,下面我就根据业务需求来介绍一个简单的自定义监控配置 ...
- React Native 系列(六) -- PropTypes
前言 本系列是基于React Native版本号0.44.3写的.在我们之前的通过props实现组件间传值的时候,大家有没有发现在父组件传递值过去,在子控件获取props的时候没有提示,那么如何能实现 ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- 对图像组成不了解?这样学习Matplotlib必走弯路!
在学习Matplotlib的过程中,大家一定会遇到这样那样的问题,比如说,背景图怎么设置?坐标轴怎么设置?坐标轴上的刻度值怎么设置?怎样在PyQt中添加Matplotlib绘图模块? 其实想要学好用好 ...
- animate.css的使用
前面的话 animate.css是一个使用CSS3的animation制作的动画效果的CSS集合,里面预设了很多种常用的动画,且使用非常简单.本文将详细介绍animate.css的使用 引入 anim ...
- 【社交系统研发日记五】ThinkSNS+如何计算字符显示长度?
今天我们来聊一下可能很多人都会头疼的东西:显示长度. 需求是这样的,在字符的显示上,两个英文单词才占一个中文或者其他语言的显示长度.如下: 上面排的是两个英文字母,一个汉字,一个Emoji.你会发现, ...
- 移动端 canvas插入多张图片生成一张可保存到手机图片
第一次写随笔,想把开发中遇到的问题与大家分享,可能会让您少走一步弯路. 先看下效果图: 代码分三部分为大家展示: 1.html 部分 <div id="myQrcontainer&qu ...