android frameworks之zygote进程

zygote进程是各个应用进程的鼻祖,每个app的进程是由zygote进程创建出来的,即app进程的父进程为zygote进程。

在系统启动时,加载bootloader,启动内核,创建init进程,在init进程中,解析init.rc,init.rc包含启动zygote进程的服务,进而启动zygote进程。

在linux中,进程是由fork()创建的,fork出的子进程除了一些内核的核心数据跟父进程不同外,其余的数据、内存都是和父进程共享的,fork()出的子进程返回值为0,父进程的返回值为父进程的pid

1、init.rc

init.rc中是通过import方式引入文件的,引入的文件通过ro.zygote的属性来控制

\system\core\rootdir\init.rc
import /init.${ro.zygote}.rc

ro.zygote的属性值可设置的值有:zygote32,zygote32_64,zygote64,zygote64_32,因此在system/core/rootdir/目录下有四个和zygote相关的rc文件

zygote32:32位模式

zygote32_64:以32位模式为主,64位模式为辅

zygote64:64位模式

zygote64_32:以64位模式为主,32位模式为辅

zygote32和zygote64一样,只是zygote64执行的是app_process64的进程;zygote32和zygote32_64的区别在宇zygote32_64多了启动zygote_secondary的进程

init.zytote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    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

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 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

以zygote32为例。

2、app_process的源码路径是在frameworks/base/cmds/app_process下,只有app_main.cpp文件,我们直接看它的main方法

int main(int argc, char* const argv[])
{
  .................
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//创建AppRuntime实例
   .................
    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;//niceName=zygote
        } 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.");
    }
}

在main方法里,主要做了创建runtime,解析参数,然后把com.android.internal.os.ZygoteInit传到runtime.start.

\frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ................
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);//初始化art
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {//启动虚拟机
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {//注册jni
        ALOGE("Unable to register all android natives\n");
        return;
    }

   .................
    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);//jni反射,由C、c++调用java,这里startClass为ZygoteInit,即调用ZygoteInit.java的main方法
     ...............              


}

AndroidRuntime::start里初始化art,启动虚拟机,注册jni,然后通过CallStaticVoidMethod方法进入到ZygoteInit.java的main方法。这里只是大概讲了一下流程,具体分析可看我的另外一篇文章《Android 通过bin二进制程序调用jar原理》

android4.4之前采用的是dalvik虚拟机,在android5.0开始用art虚拟机代替dalvik。Dalvik虚拟机也算是java虚拟机,只不过它执行的是dex文件,而不是class文件,并且dalvik虚拟机包含解析器,用来执行dex字节码,在运行时动态地将dex字节码转成本地机器码,然后再执行,这显然存在着效率问题。如果在运行时无需翻转换直接执行本地机器码,那效率会得到提升,因此art主要是解决这一问题。在应用安装时,art直接将dex转换为本地机器码,所以android5.0后APP的安装速度明显比之前的慢,但在运行效率方面也得到显著提升。在app安装中主要是通过PackageManagerServer的服务通过请求installd进程来执行的。

3、我们接着看ZygoteInit.java的main方法

frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
        ..............................
        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)) {
                zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }

        final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);//isPrimaryZygote为truen,sockename为:zygote

        if (abiList == null) {
            throw new RuntimeException("No ABI list supplied.");
        }
        ............................
        //创建socket
        Zygote.initNativeState(isPrimaryZygote);

        ZygoteHooks.stopZygoteNoThreadCreation();

        zygoteServer = new ZygoteServer(isPrimaryZygote);

        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//创建进程,【见3.1小节】

            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
            // child (system_server) process.
            if (r != null) {
                r.run();
                return;
            }
        }
........................
    if (caller != null) {
        caller.run();
    }
}

3.1小节

private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
    .................
    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",
            "--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 {
        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;
        }

        //通过native的fork()创建出一个进程
        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) {//返回值为0的是子进程
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        zygoteServer.closeServerSocket();
        return handleSystemServerProcess(parsedArgs);
    }

    return null;
}
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    //查看参数配没有为mInvokeWith配置,因此parsedArgs.mInvokeWith==null,进入else分支
    if (parsedArgs.mInvokeWith != null) {
        String[] args = parsedArgs.mRemainingArgs;
        // If we have a non-null system server class path, we'll have to duplicate the
        // existing arguments and append the classpath to it. ART will handle the classpath
        // correctly when we exec a new process.
        if (systemServerClasspath != null) {
            String[] amendedArgs = new String[args.length + 2];
            amendedArgs[0] = "-cp";
            amendedArgs[1] = systemServerClasspath;
            System.arraycopy(args, 0, amendedArgs, 2, args.length);
            args = amendedArgs;
        }

        WrapperInit.execApplication(parsedArgs.mInvokeWith,
                parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                VMRuntime.getCurrentInstructionSet(), null, args);

        throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
    } else {
        createSystemServerClassLoader();
        ClassLoader cl = sCachedSystemServerClassLoader;
        if (cl != null) {
            Thread.currentThread().setContextClassLoader(cl);
        }

        /*
         * Pass the remaining arguments to SystemServer.
         */
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mRemainingArgs, cl);//ZygoteInit.zygoteInit里主要做log和trace的配置,初始化zygote
    }

    /* should never reach here */
}

ZygoteInit.zygoteInit做log和trace的配置,通过jni初始化zygote,然后调起RuntimeInit.findStaticMain

frameworks\base\core\java\com\android\internal\os\RuntimeInit.java 
protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    Class<?> cl;

    try {
        cl = Class.forName(className, true, classLoader);//通过参数配置可以跟踪到className为com.android.server.SystemServer
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }

    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
                "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
                "Problem getting static main on " + className, ex);
    }
    return new MethodAndArgsCaller(m, argv);
}

在ZygoteInit.java的main方法包含各个函数的调用都主要是做了三个事情:创建socke,创建进程,通过反射调用com.android.server.SystemServer的main方法。

4、com.android.server.SystemServer.main()

frameworks\base\services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}
private void run() {
    try {
        ....................................
        //设置一些属性值
        ...............................
        //配置运行环境
        VMRuntime.getRuntime().clearGrowthLimit();
        ......................
        Looper.prepareMainLooper();//开启looper
        Looper.getMainLooper().setSlowLogThresholdMs(
                SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
        System.loadLibrary("android_servers");//加载libandroid_servers.so

        // Debug builds - allow heap profiling.
        if (Build.IS_DEBUGGABLE) {
            initZygoteChildHeapProfiling();
        }

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();//创建上下文

        // 把SystemServiceManager添加到服务列表
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }

    // 启动核心的服务,大概会启动90多种服务
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }
    ......................................
    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

5、总结:zygote是一个非常重要的进程,所有的应用进程都依赖它来创建,zygote的启动是由解析init.rc实现,通过rc携带的参数执行app_process程序,然后注册art,配置虚拟机参数,启动虚拟机,注册jni,创建socket,通过jni调用fork()创建新进程,通过反射执行到SystemServer.main里,最终启动系统所需的大概有90多种的核心服务。

想要学习更多编程,欢迎关注公众号:android全贯通