Zygote进程

Zygote简介

zygote是Android一个非常重要的进程,和init、systemServer进程这三个进程是Android系统非常重要的进程。

Linux的进程是通过fork产生,fork出来的进程除了一些核心数据结构和父进程不一样,其余的内存映像都是和父进程共享的。通常子进程fork出来后,会继续执行exec。exec将用一个新的可执行文件的内容替代当前进程的代码段、数据段、堆和栈。init进程启动各种service就是这样的。

Zygote创建应用却只用了fork,没有调用exec。Android应用执行的是java代码,java代码的不同才造成了应用的区别,而对于java的环境要求却是一样的。

Zygote初始化会创建虚拟机、同时把需要的系统类库和资源文件加载到内存里。zygote fork出子进程后,子进程也继承了能正常工作的虚拟机的各种系统资源,接下来子进程只需要装载apk文件中的字节码就可以运行了。

在init.rc 中zygote是通过import /init.${ro.zygote}.rc引入的,有32位、64位之分,我们主要看下32位的。

zygote是属于class main的当zygote重新启动 audioserver等一些service也会重启。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    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

app_process

app_process的main函数

这个函数主要就是解析启动参数。app_process除了能创建Zygote进程外、还能创建普通进程。我们从init.rc中传入的参数:

-Xzygote /system/bin --zygote --start-system-server。

最后niceName是zygote、startSystemServer是true zygote是true。

    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            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;
        }
    }

如果启动参数有--zygote执行ZygoteInit类,否则执行通过参数传进来的Java类。

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    }

app_process除了能启动Zygote进程,也可以使用它来执行系统的某个java类,比如am命令。

AndroidRuntime

AndroidRuntime一个Android底层的一个类,负责启动虚拟机java线程。AndroidRuntime类在一个进程中只有一个实例对象。

前面在app_process的main函数中最后调用了AndroidRuntime的start函数。这个函数主要启动虚拟机,然后通过CallStaticVoidMethod函数来调用java层的函数。这样Zygote的初始化过程转到了java层了。当然如果启动的不是Zygote而是执行的java类将是调用RuntimeInit函数。

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
           /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000;
           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /android does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    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.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        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 {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

        }
    }

ZygoteInit

ZygoteInit类负责Zygote进程java层的初始化工作。这个类的main函数主要注册了zygote的socket来监听应用程序的启动消息,加载资源、启动systemserver、然后进入socket监听等。我们需要注意这个函数已经fork了一个system_server并且zygote主线程最后在执行runSelectLoop函数监听其他应用进程启动的消息。当有启动进程的socket消息,runSelectLoop函数就会返回,当然这个时候返回是在子进程中,zygote进程还是不听监控socket,最后通过返回的caller,然后执行器run函数。这样就到应用进程的ActivityThread的main函数了。

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

        ......

        final Runnable caller;
        try {
            ......

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = 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.");
            }

            zygoteServer.registerServerSocket(socketName);//注册socket监听,用来接收启动应用启动的消息
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                preload(bootTimingsTraceLog);//加载资源

            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false, 0);

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            // Set seccomp policy
            Seccomp.setPolicy();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//启动systemserver进程

                // {@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.
            caller = zygoteServer.runSelectLoop(abiList);//监听socket消息,并且获取到java的函数入口,这里zygote会一直循环,能返回的都是fork出来的子进程
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();//这个时候在子进程中,一般调用ActivityThread的main方法了
        }
    }

请求启动应用进程

Android启动一个新的进程都是在AMS中通过其startProcessLocked函数来完成,这个我们在之前分析AMS的博客分析过了。

这个函数最后会调用如下代码,而这个entryPoint就是android.app.ActivityThread

                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, debugFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, entryPointArgs);

而最后是调用了ZygotePrcocess的startViaZygote函数,这个函数又调用了zygoteSendArgsAndGetResult函数,而zygoteSendArgsAndGetResult这个函数把会这些参数通过socket传给zygote,而我们现在的进程就是system_server。

然后我们再来看zygote进程的ZygoteInit类中main方法调用的runSelectLoop方法来监听和处理启动应用的消息。

这个函数当有事件到来才会唤醒线程,然后调用ZygoteConnection的processOneCommand分析。最后这个函数返回的是子进程的函数入口的Runnable接口。

    Runnable runSelectLoop(String abiList) {
        ......
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }

                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    try {
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);

                        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(i);
                                fds.remove(i);
                            }
                        }
                    } catch (Exception e) {
                        ......
                    }
                }
            }
        }
    }
}

processOneCommand最后调用了Zygote.forkAndSpecialize来fork了应用进程。这里我们先主要看handleChildProc函数,这里主要是调用了ZygoteInit.zygoteInit函数。

        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);//fork子进程

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

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

                return handleChildProc(parsedArgs, descriptors, childPipeFd);//子进程初始化
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;

而这个函数中调用了nativeZygoteInit主要是初始化binder,而在applicationInit中就是返回了应用进程的函数入口(也就是ActivityThread的main函数)。

    public static final Runnable zygoteInit(int targetSdkVersion, 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, argv, classLoader);
    }

我们再回到ZygoteInit的main函数,前面runSelectLoop返回的话肯定是子进程,而caller就是子进程的函数入口,后面调用caller的run函数就进入应用进程的ActivtityThread的main函数了。而Zygote的主进程依然在runSelectLoop中循环。

            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }

预加载系统类和资源

为了加快应用程序的启动,Android把系统常用的java类和一部分Framework资源在zygote进程中预加载。这些预加载的类和资源在所有经zygote进程fork出的子进程中都是共享的。

前面我们在ZygoteInit的main中调用preload方法来加载系统资源,比如系统类,系统资源、opengl资源、共享库、webview资源等。

    static void preload(TimingsTraceLog bootTimingsTraceLog) {
        preloadClasses();
        preloadResources();
        nativePreloadAppProcessHALs();
        preloadOpenGL();
        preloadSharedLibraries();
        preloadTextResources();
        WebViewFactory.prepareWebViewInZygote();
    }

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值