Zygote进程的启动、功能

1、简单了解Android系统启动时做的事情
    |---------------Android RunTime---------------------------|---------Application Framework-----------|
    RuntimeInit  ->  ZygoteInit  -> Zygote  ->  SystemServer  ->  (ActivityManagerService)
    AndroidRuntime处于Linux内核层(Kernel)以及Framework层中间
    
    Init进程是Linux环境下非常重要的一个进程
    Zygote进程是Java环境下的第一个进程,所有其他的Java环境下的进程都是由Zygote进程来进行fork的
    Init进程在启动Zygote进程之后,初始化Zygote进程之前,会先进行AndroidRuntime的启动和环境建立
    
    1)Init进程初始化做的事 参考资料:http://blog.csdn.net/yangzhihuiguming/article/details/51697801
    init进程作为linux启动过程中的一个重要的进程,它主要负责文件系统的挂载,属性的初始化,各种配置的加载启动以及Action触发,Service的启动,
    Zygote作为Java环境下的服务进程,也在Init.rc中进行了配置。

    2)Android Runtime的启动,它是在Init进程之后,zygote进程启动之后、初始化之前初始化的,所以此时它的入口和zygote的入口一致

//AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& options){
	...
	if (startVm(&mJavaVM, &env) != 0) {//启动虚拟机
		return;
	}
	onVmCreated(env);//创建VM之后释放slashClassName的内存
	if (startReg(env) < 0) {//注册Android JNI函数
		ALOGE("Unable to register all android natives\n");
		return;
	}
	...
	char* slashClassName = toSlashClassName(className);//解析类名
	jclass startClass = env->FindClass(slashClassName);//找到需要启动的java类
	if (startClass == NULL) {
		ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
	} else {//得到指定类中指定方法的ID,这里得到的是RuntimeInit.main()的方法ID
		jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
		if (startMeth == NULL) {
			ALOGE("JavaVM unable to find main() in '%s'\n", className);
		} else {//调用上面得到的方法ID和相关参数,即调用Java类ZygoteInit.main();
			env->CallStaticVoidMethod(startClass, startMeth, strArray);
			...
		}
	}
	...
}
3)系统建立AndroidRuntime的时候,创建Java虚拟机,并将系统中一些JNI函数注册到Java虚拟机中,
    此后只需要通过JNI的方法就可以调用这些Native方法,此外JNI函数的注册还有一种方法,
    即通过静态代码块System.LoadLibrary("...");来加载自定义的JNI方法。
    
2、关于Zygote进程
    Zygote是整个系统创建新进程的核心进程,Zygote进程在内部会先启动Dalvik虚拟机,继而加载一些必要的系统资源和系统类, 最后进入一种监听状态
    当其他系统模块(比如AMS)希望创建新进程时,只需向Zygote进程发出请求,Zygote进程监听到该请求后,会相应地fork出新的进程,于是这个新进程在初生之时,就先天具有了自己的Dalvik虚拟机以及系统资源。
    

    1)ZygoteInit.main(...)做的事情

public class ZygoteInit {
	...
	public static void main(String argv[]) {
		// Mark zygote start. This ensures that thread creation will throw an error.
		ZygoteHooks.startZygoteNoThreadCreation();
		try {
			Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
			RuntimeInit.enableDdms();//开启Ddms监听,监听Ddms消息
			// Start profiling the zygote initialization.
			SamplingProfilerIntegration.start();//启动性能统计
			boolean startSystemServer = false;
			String socketName = "zygote";
			String abiList = null;
			for (int i = 1; i < argv.length; i++) {
				if ("start-system-server".equals(argv[i])) {
					startSystemServer = true;
				} else if (argv[i].startsWith(ABI_LIST_ARG)) {
					abiList = argv[i].substring(ABI_LIST_ARG.length());
				} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
					socketName = argv[i].substring(SOCKET_NAME_ARG.length());
				} else {
					throw new RuntimeException("Unknown command line argument: " + argv[i]);
				}
			}
			if (abiList == null) {
				throw new RuntimeException("No ABI list supplied.");
			}
			registerZygoteSocket(socketName);//创建了一个socket接口,用来和ActivityManagerService通讯
			...
			EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
			/*
			 * http://blog.csdn.net/fu_kevin0606/article/details/54097031
			 * 在Android系统中有很多的公共资源,所有的程序都会需要。而Zygote创建应用程序进程过程,复制自身进程地址空间作为应用程序进程的地址空间,
			 * 因此在Zygote进程中加载的类和资源都可以共享给所有由Zygote进程孵化的应用程序。
			 * 所以就可以在Zygote中对公共类与资源进行加载,当应用程序启动时只需要加载自身特有的类与资源就行了,提高了应用软件的启动速度
			 */
			preload();//预加载classes、预加载resources、预加载openGL、预加载共享类库、文本资源
			...
			// Finish profiling the zygote initialization.
			SamplingProfilerIntegration.writeZygoteSnapshot();//结束统计并生成结果文件
			...
			gcAndFinalize();
			...
			// Zygote process unmounts root storage spaces.
			Zygote.nativeUnmountStorageOnInit();
			ZygoteHooks.stopZygoteNoThreadCreation();
			if (startSystemServer) {
				startSystemServer(abiList, socketName);//Fork一系列系统进程
			}
			/* 
			 * 开始Zygote进程的死循环,在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程
		  * Socket的监听方式为使用Linux系统调用select()函数监听Socket文件描述符,
		  * 当该文件描述符上有数据时,自动触发中断,在中断处理函数中去读取文件描述符中的数据
			 */
			runSelectLoop(abiList);
			closeServerSocket();
		} catch (MethodAndArgsCaller caller) {
			caller.run();
		} catch (RuntimeException ex) {
			Log.e(TAG, "Zygote died with exception", ex);
			closeServerSocket();
			throw ex;
		}
	}
	...
        
    /** fork系统进程
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Containers run without this capability, so avoid setting it in that case */
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        }
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",//这个SystemServer的run()内会创建ActivityManagerService
        };
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }


 }

Zygote启动时初始化的公共资源,在创建子进程时共享给子进程,提高了app启动速度

在Android系统中有很多的公共资源,所有的程序都会需要。而Zygote创建应用程序进程过程,复制自身进程地址空间作为应用程序进程的地址空间, 因此在Zygote进程中加载的类和资源都可以共享给所有由Zygote进程孵化的应用程序。

所以就可以在Zygote中对公共类与资源进行加载,当应用程序启动时只需要加载自身特有的类与资源就行了,提高了应用软件的启动速度

2)Zygote如何fork新进程,点击桌面应用图标时如何创建新的进程

当点击Launcher里的应用程序去启动一个新的应用程序进程时,这个请求会到达framework层的核心服务ActivityManagerService中,当AMS收到这个请求后,它通过调用Process类发出一个"孵化子进程"的Socket请求,而Zygote监听到这个请求后就立刻fork一个新的进程出来。



你可能感兴趣的:(笔记)