Zygote进程的启动

QuibblerQuibbler 2020-05-14 约 27 分钟 2167 次阅读

Zygote进程的启动

Android系统中有三个关键进程:init进程、SystemServer进程和Zygote进程。Zygote是系统运行的第一个Dalvik虚拟机进程,且负责孵化开启其它的APP应用进程。

Zygote进程是由Linux内核启动的用户级init进程启动,现在就来了解一下Zygote进程的启动流程。至于Linux进程0、内核进程是如何启动的这里不深入讨论,参考计算机专业的书籍《Linux内核设计的艺术》。

init进程启动其它服务包括Zygote都是通过init.rc文件来启动,该文件是用Android初始化语言编写。位于:/system/core/rootdir。可以看见其中首先inport了Zygote的配置文件:

...
    import /init.usb.configfs.rc
    import /init.${ro.zygote}.rc

一共有下面这四种脚本文件:

        init.zygote32.rc :纯32位模式

        init.zygote64_32.rc:混64位模式(64位为主,32位为辅)

        init.zygote64.rc:纯64位模式

        init.zygote32_64.rc:混32位模式(32位为主,64位为辅)

脚本都是Android初始化语言用来启动app_process进程,也就是以后的Zygote进程。以init.zygote64_32.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 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
    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

通过Android初始化语言启动了两个Service服务:zygote和zygote_secondary。再

执行frameworks/base/cmds/app_process/app_main.cpp目录下的app_main.cpp文件。在其中的main方法中:

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;
        }
    }
    ...
    if (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.");
    }

在Linux内核中Zygote进程通过fork自己来启动其它APP进程,并且通过zygote判断否是自己当前Zygote进程,

AndroidRuntime类定义于frameworks/base/core/jni目录下AndroidRuntime.cpp文件中,其中AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)方法:

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        ...
        /*
         * 启动JVM虚拟机
         */
        JNIEnv* env;
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
        onVmCreated(env);
        /*
         * 为JVM虚拟机注册JNI方法
         */
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
        ...
        /*
         * 启动VM。 该线程成为VM的主线程,并且在VM退出之前不会返回.
         */
        char* slashClassName = toSlashClassName(className != NULL ? className : "");
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* 继续 */
        } 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);
                /* 继续 */
            } else {
                //通过JNI调用ZygoteInit的main方法
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
    #if 0
                if (env->ExceptionCheck())
                    threadExitUncaughtException(env);
    #endif
            }
        }
        ...
    }

前面都是C++代码,在Native层。接下来到了Java框架层。

从ZygoteInit的main方法开始:

@UnsupportedAppUsage
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        ...
        Runnable caller;
        try {
            ...
            // 在某些配置中,我们避免急于预加载资源和类。
            //在这种情况下,我们会在第一个fork之前预先加载东西。
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }
            ...
            
            Zygote.initNativeState(isPrimaryZygote);
            ZygoteHooks.stopZygoteNoThreadCreation();
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    r.run();
                    return;
                }
            }
            // select循环在派生之后在子进程的早期返回,并在Zygote中永久循环。
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        
        // 我们在子进程中,已经退出选择循环。 继续执行命令。
        if (caller != null) {
            caller.run();
        }
    }

其中会调用forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer)方法返回Runnable对象。以前源码该方法名为startSystemServer。

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        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_PTRACE,
                OsConstants.CAP_SYS_TIME,
                OsConstants.CAP_SYS_TTY_CONFIG,
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
        );
        ...
        try {
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }
            /* 请求fork系统服务进程*/
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        
        /* 对于fork的子进程,也就是应用进程 */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }
        
        return null;
    }

调用Zygote.forkSystemServer方法中fork服务进程:

public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true, runtimeFlags);
        }
        ZygoteHooks.postForkCommon();
        return pid;
    }

接着又会到Native层调用底层的nativeForkSystemServer方法fork出一个Server进程。

private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

回到ZygoteInit的main方法,继续运行ZygoteServer的runSelectLoop方法,进入无限循环,处理来自AMS的Socket请求,如何处理AMS创建APP进程请求见APP进程启动流程一文。运行Zygote进程的select循环:

/**
     * 运行Zygote进程的select循环。 
     * 接受新的连接,并从连接中读取命令,一次生成一个请求。
     */
    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        //无限循环
        while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval();
            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs = null;
            // 考虑到轮询结构,请分配足够的空间
            //此Zygote的USAP池的状态(可以是常规Zygote,WebView Zygote或AppZygote)。
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            ...
        }
    }
}

相关博客:

        Zygote浅谈

        Android系统启动zyogte进程

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w