init进程
- 作用:启动关键服务、守护关键进程。
- 关键服务:ring(铃声)、电话、蓝牙、网络、系统日志、Zygote、ServiceManager等,不包过AMS,PMS等
- app保活,让服务变成init启动的服务。
//查看android 进程
adb shell
//ps 查看不到可以尝试 ps -A 或者ps -ef
ps -ef
Zygote进程
启动Zygote进程 (由nitave进程启动的进程是native进程)
-
作用
-
- 创建一个Service端的Socket,开启LocalServiceSocket 实现进程通信
-
- 加载系统类、系统资源(pp打包的时候android.jar不会被打包进去的原因)
-
- 启动system_servier
-
- 所有进程都是从Zygote进程中启动的,Zygote被杀死后系统会重启
-
init进程-读取 linux脚本文件->init.rc任务清单脚本文件
-
启动Zygote进程(linux命令 service 启动的属于native进程)
-
根据传入的参数-Xzygote app_process进程改名为zygote进程
-
JNI启动java代码 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
-
ZygoteInit 启动Socket实现进程间通信 用于App等相关进程启动
-
加载preloaded-classes文件(包含所有的app启动需要的系统源码)
- 启动System_SERVER(java 进程 fork)
为什么Zygote通信为什么用Socket,而不是Binder? 原文链接
- 先后时序问题: binder驱动是早于init进程加载的。而init进程是安卓系统启动的第一个进程。 安卓中一般使用的binder引用,都是保存在ServiceManager进程中的,而如果想从ServiceManager中获取到对应的binder引用,前提是需要注册。虽然Init进程是先创建ServiceManager,后创建Zygote进程的。虽然Zygote更晚创建,但是也不能保证Zygote进程去注册binder的时候,ServiceManager已经初始化好了。注册时间点无法保证,AMS无法获取到Zygote的binder引用,这是原因之一。
2. 多线程问题
Linux中,fork进程是不推荐fork一个多线程的进程的,因为如果存在锁的情况下,会导致锁异常。
而如果自身作为binder机制的接收者,就会创建一个额外的线程来进行处理(发送者进程是无影响的)。
所以,如果使用binder机制,就会导致去fork一个多线程的进程,这是原因之二。
- 效率问题: AMS和Zygote之间使用的LocalSocket,相对于网络Socket,减少了数据验证等环节,所以其实效率相对于正常的网络Socket会大幅的提升。虽然还是要经过两次拷贝,但是由于数据量并不大,所以其实影响并不明显。
- Binder拷贝问题: 如果使用Binder机制的话,从Zygote中fork出子进程会拷贝Zygote中Binder对象。从而多占用了一块无用的内存区域。而Binder对象不能释放。Binder的特殊性在于其是成对存在的,其分为Client端对象和Server端对象。假设我们使用Binder,如果要释放掉Server端Binder引用对象,就必须释放掉AMS中的Client端Binder对象,那这样就会导致AMS失去Binder从而无法正常向Zygote发送消息。而使用Socket通讯的话,fork出APP进程之后,APP进程会去主动的关闭掉这个Socket,从而释放这块区域。使用Binder会造成额外的内存占用
- 所有App的父进程都是Zygote ,系统类系统资源,每个App都需要,系统类都是由Zygote预加载的,防止每个App都加载一边消耗不必要资源。子进程与Zygote共享,档需要特殊操作修改时,会从内存的角度从新创建一份对应的类。