栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

安卓开机流程

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

安卓开机流程

安卓系统层次框架图如下

图片清晰地展示了Android的五层架构,从上到下依次是:应用层、应用框架层、库层、HAL层以及Linux内核层。

Android的启动流程是自下向上的,大体上可以分为三个阶段:1、BootLoader引导启动内核;2、启动Linux内核;3、启动Android系统。

Android 启动流程图如下:

1 Boot ROM

        我们长按电源按键,引导 ROM 代码从 ROM 中预定义位置开始执行。它将引导加载程序加载到 RAM 中并开始执行。存储在Boot ROM中的 Primary Bootloader (PBL)是引导过程第一阶段,此代码由芯片制造商编写;PBL验证下一阶段的真实性,如果辅助引导加载程序验证失败,则进入EDL(Emergency Download)。

        由于Boot ROM 空间有限,因此将辅助引导加载程序存储在eMMC中

2 Bootloader

        Bootloader主要是在系统加载前,初始化硬件设备,建立内存空间的映像图,为最终调用系统内核准备好环境。在 Android运行环境中里没有硬盘,而是 ROM,它类似于硬盘存放操作系统,用户程序等。ROM 跟硬盘一样也会划分为不同的区域,用于放置不同的程序

        Bootloader程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,bootloader可以根据配置参数或者输入数据设置内核。

 3 初始化Kernel

        kernel开始启动时,设置缓存、被保护存储器、计划列表,加载驱动。当初始化内核之后,就会启动一个相当重要的祖先进程,也就是init进程,在Android系统中,会有一个init.rc脚本,init进程一旦启动就会读取并解析这个脚本文件,把其中的元素整理成自己的数据结构(链表)。

 4  Zygote进程

        当init进程创建之后,会fork出一个Zygote进程,这个进程是所有Java进程的父进程。Android是基于Java的(底层也是C),所有这里就会fork出一个Zygote Java进程用来fork出其它的进程。在Zygote开启的时候,会调用ZygoteInit.main()进行初始化。

        init.rc 部分解析执行主要代码路径:systemcoreinit

        解析流程: main.cpp(SecondStageMain)->init.cpp(LoadBootscripts)->Parser.cpp(ParseConfig)

        Action执行流程:main.cpp(SecondStageMain)->->init.cpp(LoadBootscripts)->action_manager.cpp(ExecuteOneCommand)

        service 会略微复杂,有兴趣的可以自己去看看。

        通过对init.rc的解析,创建了Zygote 系统服务,在初始化时会启动虚拟机,并加载一些系统资源。这样 zygote fork 出子进程后,子进程也继承了能正常工作的虚拟机和各种系统资源,接下来只需装载 apk 文件的字节码就可以运行应用程序了,可以大大缩短应用的启动时间,这就是 zygote 进程的主要作用。

        zygote服务的启动是通过init.rc启动服务,执行的是app_process,app_process是由frameworks/base/cmds/app_process/app_main.cpp编译出来的。

#init.rc service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

        调用Android start ->startVm函数来创建虚拟机,调用startReg函数为java虚拟机注册JNI方法,通过toSlashClassName找到ZygoteInit,通过GetStaticMethedID函数找到main方法然后调用,ZygoteInit的main方法是由Java语言编写的,当前的运行逻辑在Native中,这就需要JNI来调用Java,这样Zygote就从Native层进入了Java框架层(ZygoteInit)。

        在ZygoteInit中创建zygoteServer,为其他进程初始化创建时与zygote通信做准备,

fork出了SystemServer进程

关于Zygote的疑问
  • 孵化应用进程这种事为什么不交给SystemServer来做,而专门设计一个Zygote?
  • 我们知道,应用在启动的时候需要做很多准备工作,包括启动虚拟机,加载各类系统资源等等,这些都是非常耗时的,如果能在zygote里就给这些必要的初始化工作做好,子进程在fork的时候就能直接共享,那么这样的话效率就会非常高。这个就是zygote存在的价值,这一点呢SystemServer是替代不了的,主要是因为SystemServer里跑了一堆系统服务,这些是不能继承到应用进程的。而且我们应用进程在启动的时候,内存空间除了必要的资源外,最好是干干净净的,不要继承一堆乱七八糟的东西。所以呢,不如给SystemServer和应用进程里都要用到的资源抽出来单独放在一个进程里,也就是这的zygote进程,然后zygote进程再分别孵化出SystemServer进程和应用进程。孵化出来之后,SystemServer进程和应用进程就可以各干各的事了
  • Zygote的IPC通信机制为什么不采用binder?如果采用binder的话会有什么问题么?
  • 第一个原因,我们可以设想一下采用binder调用的话该怎么做,首先zygote要启用binder机制,需要打开binder驱动,获得一个描述符,再通过mmap进行内存映射,还要注册binder线程,这还不够,还要创建一个binder对象注册到serviceManager,另外AMS要向zygote发起创建应用进程请求的话,要先从serviceManager查询zygote的binder对象,然后再发起binder调用,这来来回回好几趟非常繁琐,相比之下,zygote和SystemServer进程本来就是父子关系,对于简单的消息通信,用管道或者socket非常方便省事。第二个原因,如果zygote启用binder机制,再fork出SystemServer,那么SystemServer就会继承了zygote的描述符以及映射的内存,这两个进程在binder驱动层就会共用一套数据结构,这显然是不行的,所以还得先给原来的旧的描述符关掉,再重新启用一遍binder机制,这个就是自找麻烦了。

        systemserver 创建:

        ZygoteInit.java(main)->forkSystemServer ->Zygote.java(forkSystemServer)->nativeForkSystemServer->com_android_internal_os_Zygote.cpp(com_android_internal_os_Zygote_nativeForkSystemServer)->ForkCommon

5.SystemServer进程创建

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/314793.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号