Android启动流程

Android启动流程
Android启动流程

当我们手机按下电源后,引导芯片就会启动,然后从固化在ROM(断电后都会保存的)里面的代码执行,执行代码后,就会加载引导程序BootLoader到RAM(运行时内存,随机存储)中,然后执行,而BootLoader它执行后,会去启动操作系统,系统启动后就会启动第一个进程,也就是idle,它的pid为0,这是内核的第一个进程,也是Android系统的第一个进程,然后会启动两个进程,一个是init进程,一个是kthreadd进程,kthreadd进程主要是内核方面的工作,我们比较关心的是init进程,这个进程就是用户空间的鼻祖,init进程是个首个开辟用户空间的进程,在init之前的进程都是在内核下启动的,(用户空间:执行App代码的,应用层;内核空间:内核层,内核代码等),然后init进程fork除zygote进程,zygote--孵化器、受精卵,它会fork除system_server进程,并且我们的应用进程也是在zygote fork的,system_server进程设计到Android的一些系统服务,例如AMS、WMS、PKMS等都是由system_server进程启动的,然后就去启动app

zygote启动流程
zygote启动流程
图1app_main.cpp的main函数

AppRuntime继承自AndroidRuntime
执行runtime.start

启动虚拟机

注册JNI

调用Java的com.android.internal.os.ZygoteInit的main方法

上图1看到,app_main.cpp里面初始化了AndroidRuntime,Android运行时环境,AppRuntime继承自AndroidRuntime,接着就执行runtime.start(),这启动做了三件事情,第一件:创建了虚拟机,第二件:注册JNI,第三件:进入Java世界。

题外话:一个进程一个虚拟机,为什么要这么设计?有什么好处?
一个很明显的好处是隔离,进程是操作系统分配资源的最小单位,所以进程的内存是私有的,也就是说每个进程都是隔离的,一个进程一个虚拟机,虚拟机主要的工作是管理内存,这么一来,虚拟机管理及就非常方便了,只要管好自己进程里的内存,并且这也符合沙盒机制,进程挂掉了,也不会影响到其他进程。

进入Java层之后,做了四件事情:

1.预加载信息,
2.创建socket,
3.创建system_server进程,
4.进入无限循环。


进入Java层

预加载信息

preload(bootTimingsTraceLog);
做了什么呢?预加载了些什么,加载了些什么东西?
加载了一部分framework资源以及常用的Java类,这就是预加载做的事情。
那这么做有什么目的呢?为什么提前加载这些资源?
---为了加快应用进程的启动。

创建socket

zygoteServer = new ZygoteServer(isPrimaryXZygote);//创建socket


zygote预加载

这里socket是进程通信机制,那我们为什么不用Binder呢?
主要有两点:1.Binder在这时候还没有初始化完成,2.因为fork的原因,因为Binder是个多线程机制,用fork是不好的,fork是写时拷贝,如果是多线程的话容易死锁,所以这里用socket,而不用Binder。

*关于写时拷贝知识补充
在Linux中要启动一个新进程的方式通常是:先调用fork()函数fork出一个新的进程,然后在 新的进程中调用exec()函数来启动新的程序从而达到启动新程序的目的。
我们知道进程间的内存地址空间是隔离的,fork()系统调用的结果是生成一个新的子进程,为了保证隔离性, 早期的UNIX采用在fork()将父进程的地址空间完整的复制一份。这个操作非常的耗时。 为了提高效率现代的Unix及Linux采用了一种称为写时复制的技术,其实也就是一种延迟操作的做法, 子进程和父进程在fork()时并不马上复制,而是暂时共享内存空间,随后只要父进程或者子进程试图写共享的内存就会产生一个异常, 这时内核才把内存空间进程复制,比如我们在Shell中启动一个程序时随后就会启动新的程序,启动后的程序将会覆盖旧的内存空间, 如果提前就复制了,那么这个复制操作其实是白做了,为此系统将这个操作优化为写时复制。


zygote进程fork出system_server进程

Runnable r = forkSystemServer(abiList,zygoteSocketName,zygoteServer);
创建system_server进程

进入无限循环

call = zygoteServer.runSelectLoop(abiList);
进入无限循环 Handler的Loop,等待着,那它等待什么呢?
它在等待AMS给它发消息,去创建进程。

为什么要用zygote 去fork应用进程?而不用init?不用system_server?

因为init里面除了fork zygote以外,还会去创建很多进程,应用进程中不需要这些进程,而为什么不在system_server里面呢?因为system_server里面它会去启动很多系统服务,AMS、WMS、PKMS,接近100个服务,所有的应用进程都是公用这些服务的,并不是每个进程里面都有一套这样的服务,所以说system_server里面有很多服务,而这些服务也不是我们应用进程一定要放到一起的,可以通过进程间通信去访问这些服务就行。

zygote如何forksystem_server进程

zygote如何fork system_server进程的代码
图解zygote如何forksystem_server进程

Linux 的fork机制:
父进程执行fork(),返回子进程的ID,然后继续执行下面的程序,而fork出来的子进程执行fork()时返回值是0,用这来区分是父进程还是子进程。
fork调用的奇妙之处就是它仅仅被调用一次,却能返回两次,它可能有三种不同的返回值:
在父进程中,fork返回新创建子进程的ID
在子进程中,fork返回0
如果出现错误,fork返回一个负值
为什么fork会返回两次?
答:由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中等待返回,因此fork函数会返回两次,一次是在父进程中放回,另一次是在子进程中返回,这两次的返回值是不一样的。

子进程执行pid == 0 里面的程序

这里子进程执行pid == 0 里面的程序,处理SystemServer进程。

SystemServer里面做了些什么?

3b6d5f7946ea0d9d14a5893fd42cf18.png
82ed31c1d951ecb9bb4b859b12a95e6.png
image.png
a72b8bf33526e4d2b0341103bbf872c.png

经过一系列的操作最后反射出SystemServer.main(),放在Runnable里面的run方法里面,待执行。


image.png

在前面fork SystemServer进程的时候就是返回这个runnable,然后判断这个runnable是否为空,这里:主进程(zygote)r为空不执行,子进程(system_server)不为空,执行run方法,去创建system_server进程。

SystemServer启动流程


SystemServer启动流程

首先会去创建SystemServerManager,接着去启动我们的引导服务,再来是核心服务,再来就是其他服务,接着就是一直循环,主要我们需要掌握这四个和应用层相关的,AMS是在引导服务启动的,WMS就是在other服务启动的,PKMS也是在引导服务启动的。


image.png

这里我们就会创建SystemServiceManager,它是用来启动服务的。

image.png

然后接着往下面就会在这个地方启动三类服务,每一类服务都有很多个,特别是otherService,它就启动了大概了80个服务。

为什么AMS这些它在引导服务里面呢?而WMS却在其他服务里面呢?
答:主要是看服务的依赖关系来确定,因为AMS在其他服务会用到,比方说,像WMS,启动后马上就会和AMS进行一个关联,所以说AMS启动得比较早。

image.png

在10.0之前,这个AMS是直接启动的,10.0之后多了一个ATM服务,它调用了SystemServiceManager,去启动服务。1.反射创建Lifecycle.class,调用Lifecycle的onStart方法。

image.png

创建Lifecycle的时候就创建ATM服务。

image.png

image.png

在这个服务创建的时候,创建了一个生命周期管理类,这就是activity的生命周期管理类。然后在onStart()的publicBinderService里面,把ATM服务通过addService方法保存到ServiceManager里面。

构造方法里创建了AMS对象


image.png

AMS


image.png

创建栈管理对象
栈管理对象
image.png

这里把AMS保存在ServiceManager里,还把meminfo,gfxinfo,dbinfo,cpuinfo等加进去,这些都是Binder服务,都是跨进程的,我通过这可以获取到相关信息。

image.png

WindowManager创建,紧接着把wm装进去

image.png

image.png

systemReady里面,它就会启动Launcher界面。

你可能感兴趣的:(Android启动流程)