梳理Zygote进程-AndroidP(9.0)版本

Zygote简介

Zygote翻译为受精卵,主要用于孵化子进程。
所有的应用程序进程以及System Server进程都由Zygote进程通过fork函数孵化出来。

Zygote进程的触发

在init.rc与init.zygoteXX.rc中触发,可以查看梳理init进程文章。

Zygote进程的启动过程

在这里插入图片描述
在这里插入图片描述
main函数中传入的参数argv是
-Xzygote /system/bin --zygote --start-system-server
接着进行字符串比较如果是zygote服务zygote = true
如果是start-system-server命令 则startSystemServer = true
接下来把start-system-server放入了args
然后通过runtime.start启动进程

startVm创建虚拟机

在这里插入图片描述
查看startVM
在这里插入图片描述
代码比较多截取一部分
在这里插入图片描述
startVm方法中先进行了一些虚拟机参数的初始化,然后调用了JNI_CreateJavaVM方法
在这里插入图片描述
调用runtime.cc的Create(RuntimeArgumentMap&& runtime_options)方法
在这里插入图片描述
调用Init方法
创建堆管理对象
在这里插入图片描述
创建Java虚拟机对象、attach主线程,创建类连接器,初始化类连接器
在这里插入图片描述

startReg()注册JNI函数

在这里插入图片描述
AndroidRuntime.start()执行到最后通过反射调用到ZygoteInit.main(),
在这里插入图片描述

ZygoteInit.main()

在这里插入图片描述
1.创建Zygote服务端
2.注册Socket
3.preload资源,提前将进程所需要的资源加载,例如class、resources、openGL、公共的library、Text字体资源等。
在这里插入图片描述
4.进行一次资源的gc
5.forkSystemServer
6.zygoteServer.runSelectLoop

Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。

forkSystemServer

在这里插入图片描述

Zygote.forkSystemServer

Zygote.forkSystemServer调用nativeForkSystemServer

nativeForkSystemServer是jni方法,对应的实现在
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
在这里插入图片描述

当system_server进程创建失败时,将会重启zygote进程。这里需要注意,对于Android 5.0以上系统,有两个zygote进程,分别是zygote、zygote64两个进程,system_server的父进程,一般来说64位系统其父进程是zygote64进程

  • 当kill system_server进程后,只重启zygote64和system_server,不重启zygote;
  • 当kill zygote64进程后,只重启zygote64和system_server,也不重启zygote;
  • 当kill zygote进程,则重启zygote、zygote64以及system_server。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到此system_server进程就创建起来了,接下来进入handleSystemServerProcess方法进行初始化

ZygoteServer.closeServerSocket

forkSystemServer后会调用ZygoteServer.closeServerSocket关闭socket

handleSystemServerProcess()

调用 handleSystemServerProcess()完成system_server进程剩余的初始化工作
在这里插入图片描述

performSystemServerDexOpt

在这里插入图片描述

ZygoteInit.zygoteInit()

在这里插入图片描述

RuntimeInit.redirectLogStreams()

RuntimeInit.redirectLogStreams() 将System.out 和 System.err 输出重定向到Android 的Log系统(定义在 android.util.Log)

在这里插入图片描述

RuntimeInit.commonInit();

RuntimeInit.commonInit(); //设置了一个未捕捉异常处理方法
LogManager.getLogManager().reset();//重置log配置
设置默认的HTTP User-agent格式,用于 HttpURLConnection。
NetworkManagementSocketTagger.install();// 设置socket的tag,用于网络流量统计

ZygoteInit.nativeZygoteInit();

nativeZygoteInit()方法在AndroidRuntime.cpp中,进行了jni映射,对应下面的方法。
[–>AndroidRuntime.cpp]
此处的gCurRuntime为AppRuntime,是在AndroidRuntime.cpp中定义的
在这里插入图片描述
proc->startThreadPool();//启动新binder线程

ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver(),

applicationInit()

在这里插入图片描述
findStaticMain(args.startClass, args.startArgs, classLoader)
调用startClass的static方法 main()

在startSystemServer()方法中通过硬编码初始化参数,可知此处args.startClass为”com.android.server.SystemServer”。

在这里插入图片描述

根据注释:此抛出被ZygoteInit.main()捕获,这样做好处是能清空栈帧,提高栈帧利用率。
回到ZygoteInit.main()中
在这里插入图片描述
此处调用MethodAndArgsCaller的run方法
在这里插入图片描述

根据传递过来的参数,可知此处通过反射调用SystemServer的main方法。

zygoteServer.runSelectLoop

该方法的主要功能

  • 客户端通过openZygoteSocketIfNeeded()来跟zygote进程建立连接。zygote进程收到客户端连接请求后执行accept();然后再创建ZygoteConnection对象,并添加到fds数组列表;
  • 建立连接之后,可以跟客户端通信,进入processOneCommand()方法来接收客户端数据,并执行进程创建工作。

在这里插入图片描述
如果i>0 表示通过socket接收来自对端的数据,执行ZygoteConnection的processOneCommand方法:

    Runnable processOneCommand(ZygoteServer zygoteServer) {
124        String args[];
125        Arguments parsedArgs = null;
126        FileDescriptor[] descriptors;
127
128        try {
129            args = readArgumentList();//读取socket客户端发送过来的参数列表
130            descriptors = mSocket.getAncillaryFileDescriptors();
131        } catch (IOException ex) {
132            throw new IllegalStateException("IOException on command socket", ex);
133        }
		......
145
146        parsedArgs = new Arguments(args);//将binder客户端传递过来的参数,解析成Arguments对象格式
		......
234        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
235                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
236                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
237                parsedArgs.instructionSet, parsedArgs.appDataDir);
238
239        try {
240            if (pid == 0) {
241                // in child 子进程
242                zygoteServer.setForkChild();
243
244                zygoteServer.closeServerSocket();
245                IoUtils.closeQuietly(serverPipeFd);
246                serverPipeFd = null;
247
248                return handleChildProc(parsedArgs, descriptors, childPipeFd,
249                        parsedArgs.startChildZygote);
250            } else {
251                // In the parent. A pid < 0 indicates a failure and will be handled in
252                // handleParentProc.
253                IoUtils.closeQuietly(childPipeFd);
254                childPipeFd = null;
255                handleParentProc(pid, descriptors, serverPipeFd);
256                return null;
257            }
258        } finally {
259            IoUtils.closeQuietly(childPipeFd);
260            IoUtils.closeQuietly(serverPipeFd);
261        }
262    }

通过 Zygote.forkAndSpecialize创建新进程,pid=0时调用handleChildProc 进入子进程执行流程

总结

  1. init 根据init.rc 运行 app_process, 并携带‘–zygote’ 和 ’–startSystemServer’ 参数。
  2. AndroidRuntime.cpp::start() 里将启动JavaVM,并且注册所有framework相关的系统JNI接口。
  3. 第一次进入Java世界,运行ZygoteInit.java::main() 函数初始化Zygote. Zygote 并创建Socket的
    server 端。
  4. 然后fork一个新的进程并在新进程里初始化SystemServer. Fork之前,Zygote是preload常用的
    Java类库,以及系统的resources,同时GC()清理内存空间,为子进程省去重复的工作。
  5. SystemServer 里将所有的系统Service初始化,包括ActivityManager 和 WindowManager, 他们
    是应用程序运行起来的前提。
  6. 依次同时,Zygote监听服务端Socket,等待新的应用启动请求。
  7. ActivityManager ready 之后寻找系统的“Startup” Application, 将请求发给Zygote。 8. Zygote收到请求后,fork出一个新的进程。
  8. Zygote监听并处理SystemServer 的 SIGCHID 信号,一旦System Server崩溃,立即将自己杀死。
    init会重启Zygote.

总结和学习中,如有错误欢迎指正

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值