启动流程
Boot Rom -> Boot Loader -> Kernel -> 启动Init进程 -> Zygote进程 -> system_server进程 -> 启动AMS、WMS、PMS等服务 -> AMS启动Launcher应用的home activity
init进程(用户级别的第一个进程)
- 创建和挂载启动所需要的文件目录
- 初始化和启动属性服务
- 解析init.c配置文件并启动zygote进程
使用fork函数复制进程
- 子进程是父进程的一个复制品。它从父进程处继承了整个进程的地址空间;包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有少量信息)。因此fork函数的代价是很大的
子进程和父进程的区别
- 除了文件锁以外,其他的锁都会被继承
- 各自的进程ID和父进程ID不同
- 子进程的未决告警被清除
- 子进程的未决信号集设置为空集
多线程进程的fork调用
- 仅当前线程到子进程
- 如果当前线程有锁,锁也会被复制到子进程。子进程中没有其他方式可以解开,程序发生死锁。
- 孤儿进程:fork后,父进程和子进程交替运行,顺序不定。如果父进程先退出,子进程还没退出,子进程的父进程就变成了Init进程(任何一个进程都必须有父进程)
- 僵尸进程:如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就称为僵尸进程(只保留一些退出信息供父进程查询)
zygote进程
app_main.cpp main()
-> AndroidRunTime.start()
-> startVm()启动虚拟机
-> startReg()注册一些信息
-> 创建socket服务用于进程通信(Binder进程还没启动)
-> startSystemServer(),SystemServer会启动其他的一系列服务
AndroidRunTime
为Android应用运行所需的运行时环境,包括:
- Dalvik VM 虚拟机,解释运行Dex格式的Java程序,每个进程运行一个虚拟机(就是一些C代码,不停的去解释Dex格式的二进制码,把它们转换成机器码,然后执行,现在大部分虚拟机都支持JIT,也就是bytecode可能在运行前就已经被转换成机器码)
- Android的Java类库
- JNI:C和Java互相调用的接口
- LibC
startVm
Runtime
zygote的app_main.cpp main()函数主要做的就是参数解析,这个函数有2种启动模式:一种是zygote模式,启动zygote进程;一种是application模式,启动普通应用程序。
AndroidRunTime的startVm方法会创建Runtime对象,负责ART虚拟机运行时环境
Runtime的Init方法会开辟堆内存,后面还会用Thread开启线程,命名为“main”,也就是主线程
- 通过Heap创建堆内存管理对象
- 通过JavaVMExt创建Java虚拟机对象
- Thread::Attach连接主线程
- new ClassLinker创建类连接器,并初始化
zygote的main函数
- 新建ZygoteServer服务器端,注册socket
- Preload函数预加载资源,包括指定的类,Android的资源,比如drawablecolor,openGL,加载共用的Library,text资源字体等。系统启动过程中,这一块耗时比较长。
- 然后主动开启一次GC
- 然后通过forkSystemServer方法fork出SystemServer进程
- zygoteServer.runSelectLoop会监听客户端创建进程的请求,收到请求就Fork进程
为什么不从init进程Fork Android的进程,而是从Zygote进程fork?
这是因为zygote进程已经通过Preload函数预加载了很多资源,fork以后新进程就有了,从init的话就得重新加载一遍,非常耗时
那为什么不从SystemServer进程fork新的APP进程呢?
因为SystemServer进程里开启了一系列的AMS、PMS等80多个服务,APP进程是不需要的
forkSystemServer
- 最终会调用到Linux的fork函数,fork出的是zygote进程
- fork成功后,会关闭closeServerSocket服务,因为SystemServer进程不需要socket
- 接着会逐步调用到SystemServer的main函数
SystemServer的main函数
- 创建系统上下文,SystemContext;会通过ActivityThread来创建Instrumentation;通过ContextImpl创建SystemContext对象,然后创建LoadAPK对象–>创建Application和ClassLoader
- 启动AMS、PMS、WMS等80多个Android服务
- 服务都启动完成以后,会调用Looper.loop()
- 最后启动Launcher程序
以上是系统启动流程的总结,面试的时候经常会问,建议收藏起来以备不时之需。
有问题也欢迎留言讨论。
END
点亮【赞和在看】,让钱和爱都流向你。
心里种花,人生才不会荒芜,如果你也想一起成长,请点个关注吧。
作者介绍
中年程序猿,十年移动端开发老司机,分享一线开发经验和知识,正在探索通过副业渡过中年危机
越努力越幸运,加油