当前位置:   article > 正文

Zygote如何fork一个进程_zygote fork

zygote fork

上一篇我们对Launcher启动的过程做了一个跟踪,跟踪到AMS通过socket向Zygote请求fork新进程之后就停止追踪了,现在我们单独写一篇,接着上一篇,当然也不仅仅是针对Launcher,对进程的fork过程做一个跟踪和了解

1. Android系统启动流程图

在这里插入图片描述

2. fork过程的流程图和调用堆栈

由于Zygote进程在启动时会创建Java虚拟机,因此通过fork而创建的Launcher程序进程可以在内部获取一个Java虚拟机的实例拷贝。fork采用copy-on-write机制,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用

fork过程的架构流程如下图所示:
在这里插入图片描述
Zygote的调用栈关系如下图所示:
在这里插入图片描述

3. Zygote fork过程源码跟踪

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

循环等待接收到消息后,调用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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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 */);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

ZygoteInit.zygoteInit如下:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) {
   
    RuntimeInit.commonInit(); //初始化运行环境 
    ZygoteInit.nativeZygoteInit(); //启动Binder线程池 
     
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/227936
推荐阅读
相关标签
  

闽ICP备14008679号