【Android 源码学习】Zygote启动原理

Android 源码学习 Zygote启动原理

望舒课堂 Zygote进程启动原理学习记录整理。

Zygote简介

Zygote是进程在init进程启动时创建的,进程本身是app_process,来源于/system/core/rootdir/init.zygote64_32.rc。

// 主模式
service zygote /system/bin/app_process64 -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
    task_profiles ProcessCapacityHigh MaxPerformance
// 辅模式
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    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
    task_profiles ProcessCapacityHigh MaxPerformance

本身会根据系统是否支持64位来加载对应的rc文件。

import /system/etc/init/hw/init.${ro.zygote}.rc

zygote.rc所在目录
Zygote进程用来创建DVM(Dalvik虚拟机)和ART、应用程序进程和SystemServer进程。它通过fock的形式来创建应用程序和SystemServer进程,由于Zygote进程在启动时会创建DVM或者ART,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例拷贝。
在app_main.cpp的main方法中 通过linux系统下的pctrl调用pthread_setname_np,设置了app_process进程名字。

Zygote进程启动过程

app_main.cpp AndroidRuntime.cpp ZygoteInit.java ZygoteServer.java runtime.start app_main.cpp的main中调用 ZygoteInit.main(jni调用) forkSystemServer new ZygoteServer ZygoteServer.runSelectLoop app_main.cpp AndroidRuntime.cpp ZygoteInit.java ZygoteServer.java

app_main.cpp

/frameworks/base/cmds/app_process/app_main.cpp
main 方法关键代码:

int main(int argc, char* const argv[])
{
	...
	AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
	...
	 while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
        	// 如果当前运行在Zygote进程,则将zygote设置true
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
        	// 如果当前运行在SystemServer进程,则将startSystemServer设置true
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    ...
    if (!niceName.isEmpty()) {
    	// 更改进程名
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
    	// AppRuntime的基类AndroidRuntime的start 去启动zygote
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

AndroidRuntime.cpp

/frameworks/base/core/jni/AndroidRuntime.cpp
start方法核心代码

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
	......
	/* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    // 创建JNIEnv
    JNIEnv* env;
    //启动java虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     * 为java虚拟机注册Android 的java方法
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    // 从app_main的main函数的传过来的值className = "com.android.internal.os.ZygoteInit"
    //app_main:336: runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
     // 将className的"."替换为"/"
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    // 找到对应的类(ZygoteInit)
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
    	// 找到ZygoteInit的main方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        	// 通过JNI调用ZygoteInit.main
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    ......
}

ZygoteInit.java

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
zygoteInit的关键代码:

  public static void main(String argv[]) {
  	  ......
  	  // 创建ZyoteServer
  		zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
            	// fork SystemServer进程
                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;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            // 轮询,等待AMS请求
            caller = zygoteServer.runSelectLoop(abiList);  	  
  }

	private static Runnable forkSystemServer(String abiList, String socketName,
	            ZygoteServer zygoteServer) {
		......
		 /* Hardcoded command line to start the system server */
		 // 创建args 数组,用来保存启动SystemServer的启动参数
        String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;

        int pid;

        try {
        	// 参数传入ZygoteArguments 用于后续参数调用
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }

            /* Enable gwp-asan on the system server with a small probability. This is the same
             * policy as applied to native processes and system apps. */
            parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            // 创建子进程(SystemServer进程)
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        // 当前代码逻辑运行在子进程中
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            // 处理SystemServer进程
            return handleSystemServerProcess(parsedArgs);
        }
	}
	......

ZygoteServer.java

/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
ZygoteServer 的关键代码

 Runnable runSelectLoop(String abiList) {
 	  ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
      ArrayList<ZygoteConnection> peers = new ArrayList<>();
	  // mZygoteSocket 创建ZygoteServer时创建的服务端的socket
	  // 获取mZygoteSocket的文件描述
      socketFDs.add(mZygoteSocket.getFileDescriptor());
      peers.add(null);
      mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
		
		// 等待AMS请求zygote进程 创建新的应用程序进程
      while (true) {
      	......
      	
 		/*
		 * For reasons of correctness the USAP pool pipe and event FDs
		 * must be processed before the session and server sockets.  This
		 * is to ensure that the USAP pool accounting information is
		 * accurate when handling other requests like API blacklist
		 * exemptions.
		 */
 		int pollIndex = 0;
		for (FileDescriptor socketFD : socketFDs) {
			pollFDs[pollIndex] = new StructPollfd();
			pollFDs[pollIndex].fd = socketFD;
			pollFDs[pollIndex].events = (short) POLLIN;
			++pollIndex;
         }
         ......
         ZygoteConnection connection = peers.get(pollIndex);
         // connection.processOneCommand 创建新的应用程序进程
         final Runnable command = connection.processOneCommand(this);

         // TODO (chriswailes): Is this extra check necessary?
         if (mIsForkChild) {
         // We're in the child. We should always have a command to run at
         // this stage if processOneCommand hasn't called "exec".
         if (command == null) {
         	throw new IllegalStateException("command == null");
         }

         return command;
         } else {
         // We're in the server - we should never have any commands to run.
         if (command != null) {
         	throw new IllegalStateException("command != null");
         }

         // We don't know whether the remote side of the socket was closed or
         // not until we attempt to read from it from processOneCommand. This
         // shows up as a regular POLLIN event in our regular processing
         // loop.
         if (connection.isClosedByPeer()) {
         	connection.closeSocket();
         	peers.remove(pollIndex);
         	socketFDs.remove(pollIndex);
         }
         ......
      }
 }

总结

  1. 调用AndroidRuntime的start函数,启动Zygote进程
  2. 创建java虚拟机并为Java虚拟机注册JNI方法。
  3. 通过JNI调用ZygoteInit的main方法进入Zygote的Java框架层。
  4. 创建服务端Socket,并通过runSelectLoop方法等待AMS的请求来创建新的应用程序进程。
  5. 启动SystemServer进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值