开机是建立并运行系统的过程,在日常的开发中也常常会接触到,本次以开机流程为切入点,继续深入了解Android系统.
在Android系统上,我们可以把开机分为3个层次,分别是:Bootloader-->kernel-->Android,其中bootloader比较常用的有U-boot和little-kernel, qcom用的是little-kernel,很多国产平台用的是U-boot,这里也以使用量比较多的U-boot为例进行说明.
U-boot启动阶段
通过查看开机时的串口log,我们可以清楚地看到uboot启动的流程,量产阶段的uboot启动打印信息较少,我们通过修改 uboot/include/common.h的#ifdef DEBUG前定义一个#define DEBUG,之后,重编uboot,刷机,就可以看到uboot的信息量增加了很多.
下面,我们来简单介绍一下uboot的启动流程,分为两个部分,第一部分是BL1,对应uboot-spl.bin,第二部分是BL2,对应uboot.bin,这样分是因为内存不足问题而做的改进,SoC的内部一般都有一小块存储空间,分为RAM和ROM两部分,ROM中固化了BL0阶段的代码,主要是初始化外部存储器,并加载BL1阶段的代码到内部RAM上,而这块RAM空间很小,比如只有16K,这不足以使用全功能的uboot,所以,这个阶段,通常是初始化外部器件(如外部RAM),并加载BL2阶段的代码到外部RAM,uboot全功能代码由BL2阶段完成.当然,uboot也为我们开发了省去BL2这个步骤的流程,不过,这种操作不常用.
下面,我们简单介绍一下这个流程,更详细流程请参考这位大神的uboot系列文章:https://blog.csdn.net/ooonebook/article/details/
uboot BL1阶段流程.
uboot BL2阶段流程.
Linux启动阶段
同样,我们可以通过开机log看出其启动的流程,为了能够看到开机的全部log,我们需要修改loglevel,这个值可以在dts中修改,也可以在menuconfig中修改,或者是uboot的bootargs传参中添加loglevel = 8(或者7,都可以),之后,就会在Linux启动起来之后,打印全部log.
这里简单的说一下啊Linux启动的流程,详细流程可以参考着位大神的Linux系列文章:https://blog.csdn.net/ooonebook/article/details/
Android启动阶段
以Android 8.1为例子进行讲解,大致流程如下:
OS-Level前边已经贴图进行了简要的说明,下面从init入口,重点说一下Native-Level和Java-Level这两部分.
init是第一个用户空间进程,在Android上,它会构建后续Android的系统,它的主要工作可分为以下几项:
a).创建文件系统目录并挂载相关的文件系统
b).初始化log系统
c).完成SELinux相关工作
d).初始化/设置/启动属性相关的资源
e).解析init.rc
f).atcion/service管理
a).创建文件系统目录并挂载相关的文件系统
在Android 8.0之前,挂载是通过触发do_mount_all来做的,从8.0开始,以前由do_mount_all来做的事情现在分成两部分,新增FirstStageMount,将system/vendor/odm分区挂载放在FirtstStageMount阶段来做,而其它分区的挂载仍然在do_mount_all阶段, 系统启动时,在kernel挂载ramdisk.img,接着在init里面会分别把system.img和userdata.img挂载到ramdisk下的目录.
main() @ system/core/init/init.cpp为rootfs建立必