UBOOT
第一阶段是从存储介质中读取小部分程序到cpu中,这部分程序要完成引导linux所用的硬件的初始化,以及加载uboot其余程序到RAM中;
第二阶段是继续初始化必备硬件,加载linux镜像到RAM中,把执行权限交给linux,完成使命。
KERNEL
当u-boot开始执行bootcmd命令,就进入linux内核启动阶段
与u-boot类似,普通Linux内核的启动过程也可以分为两个阶段,但针对压缩了的内核如uImage就要包括内核自解压过程了。第一阶段为内核自解压过程,第二阶段主要工作是设置ARM处理器工作模式、使能MMU、设置一级页表等,而第三阶段则主要为C代码,包括内核初始化的全部工作,下面是详细介绍。
一、Linux内核自解压过程
内核压缩和解压缩代码都在目录kernel/arch/arm/boot/compressed,编译完成后将产生head.o、misc.o、piggy.gzip.o、vmlinux、decompress.o这几个文件,head.o是内核的头部文件,负责初始设置;misc.o将主要负责内核的解压工作,它在head.o之后;piggy.gzip.o是一个中间文件,其实是一个压缩的内核(kernel/vmlinux),只不过没有和初始化文件及解压文件链接而已;
二、Linux内核启动第一阶段stage1
承接上文,这里所以说的第一阶段stage1就是内核解压完成并出现Uncompressing Linux...done,booting the kernel.之后的阶段。该部分代码实现在arch/arm/kernel【或者kernel-3.18\arch\arm64\kernel】的 head.S中,该文件中的汇编代码通过查找处理器内核类型和机器码类型调用相应的初始化函数,再建立页表,最后跳转到start_kernel()函数开始内核的初始化工作。
三、Linux内核启动第二阶段stage2
start_kernel函数是进入系统内核初始化后的入口函数,它主要完成剩余的与硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程- init 进程并等待用户进程的执行,这样整个 Linux内核便启动完毕
四、挂载根文件系统
根文件系统至少包括以下目录:
/etc/:存储重要的配置文件。
/bin/:存储常用且开机时必须用到的执行文件。
/sbin/:存储着开机过程中所需的系统执行文件。
/lib/:存储/bin/及/sbin/的执行文件所需的链接库,以及Linux的内核模块。
/dev/:存储设备文件。
注:五大目录必须存储在根文件系统上,缺一不可。
Linux内核启动后的最后一个动作,就是从根文件系统上找出并执行init服务。Linux内核会依照下列的顺序寻找init服务:
1)/sbin/是否有init服务
2)/etc/是否有init服务
3)/bin/是否有init服务
4)如果都找不到最后执行/bin/sh
找到init服务后,Linux会让init服务负责后续初始化系统使用环境的工作,init启动后,就代表系统已经顺利地启动了linux内核。启动init服务时,init服务会读取/etc/inittab文件,根据/etc/inittab中的设置数据进行初始化系统环境的工作。/etc/inittab定义init服务在linux启动过程中必须依序执行以下几个Script:
/etc/rc.d/rc.sysinit
/etc/rc.d/rc
/etc/rc.d/rc.local
/etc/rc.d/rc.sysinit主要的功能是设置系统的基本环境,当init服务执行rc.sysinit时 要依次完成下面一系列工作:
(1)启动udev
(2)设置内核参数
执行sysctl –p,以便从/etc/sysctl.conf设置内核参数
(3)设置系统时间
将硬件时间设置为系统时间
(4)启用交换内存空间
执行swpaon –a –e,以便根据/etc/fstab的设置启用所有的交换内存空间。
(5)检查并挂载所有文件系统
检查所有需要挂载的文件系统,以确保这些文件系统的完整性。检查完毕后以可读可写的方式挂载文件系统。
(6)初始化硬件设备
Linux除了在启动内核时以静态驱动程序驱动部分的硬件外,在执行rc.sysinit时,也会试着驱动剩余的硬件设备。rc.sysinit驱动的硬件设备包含以下几项:
a)定义在/etc/modprobe.conf的模块
b)ISA PnP的硬件设备
c)USB设备
(7)初始化串行端口设备
Init服务会管理所有的串行端口设备,比如调制解调器、不断电系统、串行端口控制台等。Init服务则通过rc.sysinit来初始化linux的串行端口设备。当rc.sysinit发现linux才能在这/etc/rc.serial时,才会执行/etc/rc.serial,借以初始化所有的串行端口设备。因此,你可以在/etc/rc.serial中定义如何初始化linux所有的串行端口设备。
(8)清除过期的锁定文件与IPC文件
(9)建立用户接口
在执行完3个主要的RC Script后,init服务的最后一个工作,就是建立linux的用户界面,好让用户可以使用linux。此时init服务会执行以下两项工作:
(10)建立虚拟控制台
Init会在若干个虚拟控制台中执行/bin/login,以便用户可以从虚拟控制台登陆linux。linux默认在前6个虚拟控制台,也就是tty1~tty6,执行/bin/login登陆程序。当所有的初始化工作结束后,cpu_idle()函数会被调用来使系统处于闲置(idle)状态并等待用户程序的执行。至此,整个Linux内核启动完毕。整个过程见图4。