赞
踩
上一篇我们对Launcher启动的过程做了一个跟踪,跟踪到AMS通过socket向Zygote请求fork新进程之后就停止追踪了,现在我们单独写一篇,接着上一篇,当然也不仅仅是针对Launcher,对进程的fork过程做一个跟踪和了解
由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的Launcher程序进程可以在内部获取一个Java虚拟机的实例拷贝。fork采用copy-on-write机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用
fork过程的架构流程如下图所示:
Zygote的调用栈关系如下图所示:
Zygote先fork出SystemServer进程,接着进入循环等待,用来接收Socket发来的消息,用来fork出其他应用进程,比如Launcher
public static void main(String argv[]) { ... Runnable caller; .... if (startSystemServer) { //Zygote Fork出的第一个进程 SystmeServer Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); if (r != null) { r.run(); return; } } ... //循环等待fork出其他的应用进程,比如Launcher //最终通过调用processOneCommand()来进行进程的处理 caller = zygoteServer.runSelectLoop(abiList); ... if (caller != null) { caller.run(); //执行返回的Runnable对象,进入子进程 } } // ZygoteServer::runSelectLoop -> ZygoteConnection::processOneCommand
循环等待接收到消息后,调用processOneCommand处理:
Runnable processOneCommand(ZygoteServer zygoteServer) { int pid = -1; ... //fork子进程,得到一个新的pid //fork子进程,采用copy on write方式,这里执行一次,会返回两次 //pid=0 表示Zygote fork子进程成功 //pid > 0 表示子进程的真正的PID pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion); ... if (pid == 0) { // in child, fork成功,第一次返回的pid = 0 ... return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.mStartChildZygote); } else { //in parent ... childPipeFd = null; handleParentProc(pid, descriptors, serverPipeFd); return null; } }
pid为0表示fork成功,但此pid并不是fork出的子进程真正的pid,仅表示fork成功与否的标志。接下来看fork成功后执行的handleChildProc方法:
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) { ... if (parsedArgs.mInvokeWith != null) { ... throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { // App进程将会调用到这里,执行目标类的main()方法 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }
ZygoteInit.zygoteInit如下:
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
RuntimeInit.commonInit(); //初始化运行环境
ZygoteInit.nativeZygoteInit(); //启动Binder线程池
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。