Android zygote进程启动过程

zygote启动过程中涉及到以下模块:

  • app_process
  • zygote
    • USAP
    • socket
    • FileDescriptor (FD)
  • AndroidRuntime
  • AppRuntime (定义于app_process模块,继承自AndroidRuntime。)

init进程启动zygote进程:

#init.zygote32_64.rc
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks
一、绑定socket

init.zygote32_64.rc脚本中分别定义了32位(primary)和64位(secondary)zygote进程的启动参数,在/dev/socket/下创建UNIX域的socket,并把socket的fd传给对应的进程。

在这里插入图片描述

“ANDROID_SOCKET_zygote”,"ANDROID_SOCKET_zygote_secondary"分别为两个zygote的socket在环境变量中对应的key值,通过key获取对应的value,创建FileDescriptor对象。通过 “ls -l /proc/${pid}/fd” 命令可查看对应进程的所有fd指向的符号链接。

    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
    
    
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;	// ANDROID_SOCKET_zygote

        try {
    
    
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);			// env="20"
        } catch (RuntimeException ex) {
    
    
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }

        try {
    
    
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
    
    
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }
二、zygote启动

app_process进程:

//app_main.cpp
int main(int argc, char* const argv[])
{
    
    
  //...
    if (zygote) {
    
    
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
    
    
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } 
}

变量runtime是AppRuntime对象,调用AndoridRuntime对象start()方法:

//AndroidRuntime.cpp
/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    
    
  //...
  
    /* start the virtual machine 
    * 1.启动Java虚拟机。
    */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
    
    
        return;
    }
    onVmCreated(env);
  
  	 /*
     * Register android functions.
     * 2.注册JNI方法。
     */
    if (startReg(env) < 0) {
    
    
        ALOGE("Unable to register all android natives\n");
        return;
    }
      
     /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     * 3.启动对应类的静态 main()。
     */
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
}

启动zygote时className变量是"com.android.internal.os.ZygoteInit",查看其main()方法:

//ZygoteInit.java
public static void main(String[] argv) {
    
    
  //...
  
  /*
  * 1. 执行预加载。
  */
  if (!enableLazyPreload) {
    
    
  	preload(bootTimingsTraceLog);
  }
  
  /*
  * 2. 实例化ZygoteServer()对象,
  *   1).初始化 Zygote server socket。
  *   2).初始化 USAP pool server socket。
  *   3).初始化 USAP pool event FD。
  */
  zygoteServer = new ZygoteServer(isPrimaryZygote);
  
  /*
  * 3. 启动 system_server进程,
  */
  if (startSystemServer) {
    
    
      Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

      // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
      // child (system_server) process.
      if (r != null) {
    
    
           r.run();
           return;
      }
   }
  
  /*
  *	4. 循环接受处理 socket 事件。
  */
  // The select loop returns early in the child process after a fork and
  // loops forever in the zygote.
  caller = zygoteServer.runSelectLoop(abiList);
}
三、处理socket消息

ZygoteServer接收到socket消息后,调用processOneCommand方法解析消息参数。

//ZygoteServer.java
                            ZygoteConnection connection = peers.get(pollIndex);
                            final Runnable command = connection.processOneCommand(this);

最终在Zygote类的forkAndSpecialize方法中调用nativeForkAndSpecialize()方法fork新进程:

//Zygote.java
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
    
    
        ZygoteHooks.preFork();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
                bindMountAppStorageDirs);
                ZygoteHooks.postForkCommon();
        return pid;
    }

重点查看ZygoteConnection类的processOneCommand()方法:

在nativeForkAndSpecialize()方法fork新进程后,通过判断返回的pid是否大于0区分母子进程。

​ fork是类Unix操作系统上创建进程的主要方法。fork用于创建子进程(等同于当前进程的副本),新的进程要通过老的进程复制自身得到,这就是fork!

​ fork作为一个函数被调用。这个函数会有两次返回,将子进程的PID返回给父进程,0返回给子进程。(如果小于0,则说明创建子进程失败)。

//ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
    
    
    //...
    	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.mIsTopApp,
                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);

        try {
    
    
            if (pid == 0) {
    
    
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
            } else {
    
    
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, serverPipeFd);
                return null;
            }
        } finally {
    
    
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
}

所以可以看到handleChildProc()和handleParentProc()分别处理的是子进程,母进程的逻辑。

最终子进程执行zygoteInit()方法完成一个Android 应用程序的启动(初始化)

    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
    
    
        if (RuntimeInit.DEBUG) {
    
    
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

ZygoteInit.nativeZygoteInit(); 使支持Binder进程间通信机制。

RuntimeInit.applicationInit(); 调用ActivityThread.main()方法,启动UI线程。

猜你喜欢

转载自blog.csdn.net/qq_36063677/article/details/129235187