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界面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,837评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,196评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,688评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,654评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,456评论 6 406
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,955评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,044评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,195评论 0 287
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,725评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,608评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,802评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,318评论 5 358
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,048评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,422评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,673评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,424评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,762评论 2 372

推荐阅读更多精彩内容