1)压缩与非压缩内核映象
非压缩内核映象是真正的 Linux 内核代码。压缩内核映象是把非压缩内核映象作为数据进行
压缩打包,并加上了解压缩代码。也就是说,它是一个自解压的可执行映象。压缩内核映象
执行时,先解压内部包含的数据块(即非压缩内核映象),再去执行非压缩内核映象。
非压缩内核映象由 make Image 命令产生。其生成过程是:
(1) 内核的各个模块经过编译,链接,在内核源代码的顶层目录下生成 vmlinux 文件,这是
一个 ELF 格式的映象
(2) 用 arm-linux-objcopy 命令把 vmlinux 转换为二进制格式映象 arch/arm/boot/Image
压缩内核映象由 make zImage 命令产生,其生成过程是:
(1) 用 gzip 对 非 压 缩 内 核 二 进 制 映 象 arch/arm/boot/ Image 进 行 压 缩 , 生 成
arch/arm/boot/compressed/piggy.gz 文件
(2) arch/arm/boot/compressed/目录下有三个文件:piggy.s,定义了一个包含./piggy.gz 文件的
数据段;head.S 包含了对 gzip 压缩过的内核进行解压的代码;vmlinux-lds 是链接脚本。
这几个文件经过编译链接,在 arch/arm/boot/compressed/目录下产生 vmlinux 文件,这是
一个 ELF 格式的映象
(3) 用 arm-linux-objcopy 命令把 arch/arm/boot/compressed/vmlinux 转换为二进制格式映象:
arch/arm/boot/compressed/zImage
下面是make up_w_picpath 的全过程
$(TOPDIR)/vmlinux
非压缩内核,ELF格式
|
|
arch/arm/boot/Image
非压缩内核,BIN格式
|
arch/arm/boot/compressed/piggy.gz
压缩内核,gzip格式
|
arch/arm/boot/compressed/piggy.s
汇编源文件,只定义了一个包
含./piggy.gz的数据段
arch/arm/boot/compressed/head.S
汇编源文件,包含对gzip压缩内核进
行解压的代码
arch/arm/boot/compressed/vmlinux-lds
压缩内核连接脚本
|
arch/arm/boot/compressed/
vmlinux
具备自解压功能的压缩内核
ELF格式
|
arch/arm/boot/zImage
具备自解压功能的压缩内核
BIN格式
2) 内核入口
Linux 内核编译连接后生成的 ELF 映像文件是 vmlinux,从内核源代码顶层目录下的
Makefile(即顶层 Makefile)中可以找到 vmlinux 的生成规则:
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
其中$(vmlinux-lds)是编译连接脚本,对于 ARM 平台,就是 arch/arm/kernel/vmlinux-lds 文件。
vmlinux-init 也在顶层 Makefile 中定义:
vmlinux-init := $(head-y) $(init-y)
head-y 在 arch/arm/Makefile 中定义:
head-y:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
…
ifeq ($(CONFIG_MMU),)
MMUEXT := -nommu
endif
对于有 MMU 的处理器,MMUEXT 为空白字符串,所以 arch/arm/kernel/head.O 是第一个连
接的文件,而这个文件是由 arch/arm/kernel/head.S 编译产生成的。
综合以上分析,可以得出结论,非压缩 ARM Linux 内核的入口点在 arch/arm/kernel/head.s
中。
3) 汇编语言启动代码
先来看 arch/arm/kernel/head.S 的源代码(详情看资料里)
4)执行init进程
init进程是所有进程的起点,内核在完成内核引导后,即在本线程(进程)空间内加载init程序,它的进程号为1
init进程是所有进程的发起者和控制者
init进程有两个作用:
扮演终结父进程的角色:所有的孤儿进程都会被init进程接管
进入某个特定的运行级别时运行相应的程序,以此对各种运行级别进行管理,这个作用由/etc/inittab文件定义的
5)通过/etc/inittab文件进行初始化
init进程的工作是根据/etc/inittab来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等,对于RedHat来说,按以下顺序执行
a)执行/etc/rc.d/rc.sysinit(由init执行的第一个脚本)
此步可进行的工作有:
设置$PATH变量
配置网络
为虚拟内存启动交换
设置系统的主机名
检查root文件系统,以进行必要的修复
检查root文件系统的配额
为root文件系统打开用户和组的配额
以读/写的方式重新装载root文件系统
清除被装载的文件系统表/etc/matb
把root文件系统输入到mtab
使用系统为装入模块做准备
查找模块的相关文件
检查文件系统,以进行必要的修复
加载所有其他文件系统
清除几个/etc文件,如/etc/mtab、/etc/fastboot和/etc/nologin
删除UUCP的lock文件
删除过时的子系统文件
删除过时的pid文件
设置系统时钟
打开交换
初始化串行端口
装入模块
b)执行/etc/rc.d/rcX.d[KS]
首先终止K开头的服务(用来关闭一个服务),然后启动S开头的服务(用来启动一个服务)
对每一个运行级别来说,在/etc/rc.d子目录中都有一个对应的下级目录。
这些运行级别的下级子目录的命名方法上rcX.d, 其中X就是代表运行级别的数字
在各个运行级别的子目录中,都建立有到/etc/rc.d/init.d子目录中命令脚本程序的符号链接
链接的名称在K与S后有一个数字,表示执行顺序,数字小的先执行如K01tog-pegasus 、 S00microcode_ctl
对以K开头的脚本执行时系统会传递stop参数,而S开头的脚本系统会传递start参数
c)执行/etc/rc.d/rc.local
Redhat中运行模式2,3,5都把/etc/rc.d/rc.local作为初始化脚本中的最后一个文件,所以用户可以自己在这个文件中添加一些需要在其他初始化工作之后,登陆之前执行的命令
6)执行/bin/login
login程序会提示使用者需输入帐号与密码,接着编码并确认密码的正确性,若二者相合,则为使用者进行初始化环境,并将控制权交给shell,即等用户登录。