前面两篇一直在介绍init进程的内容,这一节介绍Android最重要的一个进程zygote,zygote翻译成中文就是受精卵、孵化器的意思,换言之,Android的framework层和其他的进程都是由它孵化出来的,可想而知有多么的重要。

        zygote在init.rc中的描述如下,

        service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
                class main
                socket zygote stream 660 root system
                onrestart write /sys/android_power/request_state wake
                onrestart write /sys/power/state on
                onrestart restart media
                onrestart restart netd

        从参数中可以看出,zygote进程程序位于/system/bin/app_process,代码位于/framework/base/cmds/app_process/app_main.cpp中

        它的main函数很简单,主要完成以下几件事情,

        定义一个runtime用来跑虚拟机,因为后面要运行java代码,必然要跑虚拟机

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

        解析传进来的参数

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

if (!niceName.isEmpty()) {        runtime.setArgv0(niceName.string());        set_process_name(niceName.string());    }

        运行zygoteinit

if (zygote) {        runtime.start("com.android.internal.os.ZygoteInit", args);    } else if (className) {        runtime.start("com.android.internal.os.RuntimeInit", args);    } else {        fprintf(stderr, "Error: no class name or --zygote supplied.\n");        app_usage();        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");        return 10;    }

        runtime.start的定义是

void AndroidRuntime::start(const char* className, const Vector& options)

        这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。我们重点关注zygote的main方法

    if (startVm(&mJavaVM, &env) != 0) {        return;    }
    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);    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);#if 0            if (env->ExceptionCheck())                threadExitUncaughtException(env);#endif        }    }

因为zygoteinit是java代码,所以上面要启动VM

zygoteinit的main函数主要作了三件事情,

一个调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯

            registerZygoteSocket(socketName);            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                SystemClock.uptimeMillis());            preload();            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                SystemClock.uptimeMillis());

    private static void registerZygoteSocket(String socketName) {        if (sServerSocket == null) {            int fileDesc;            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;            try {                String env = System.getenv(fullSocketName);                fileDesc = Integer.parseInt(env);            } catch (RuntimeException ex) {                throw new RuntimeException(fullSocketName + " unset or invalid", ex);            }            try {                sServerSocket = new LocalServerSocket(                        createFileDescriptor());            } catch (IOException ex) fileDesc{                throw new RuntimeException(                        "Error binding to local socket '" + fileDesc + "'", ex);            }        }    }
       这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的。这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释init.rc文件中的service命令的。每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了,然后得到的文件描述符通过publish_socket函数写入到环境变量中去

        因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须要通过文件名来连接这个LocalServerSocket了


二是预加载

static void preload() {        Log.d(TAG, "begin preload");        preloadClasses();        preloadResources();        preloadOpenGL();        preloadSharedLibraries();        // Ask the WebViewFactory to do any initialization that must run in the zygote process,        // for memory sharing purposes.        WebViewFactory.prepareWebViewInZygote();        Log.d(TAG, "end preload");    }

三是调用startSystemServer函数来启动SystemServer组件,

四是调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。

至此,zygote进程就结束了,它会一直循环在这里,等待其他进程请求它孵化出新的进程。


        在startSystemServer中,会创建一个新的子进程来执行handleSystemServerProcess

    private static boolean startSystemServer(String abiList, String socketName)            throws MethodAndArgsCaller, RuntimeException {        long capabilities = posixCapabilitiesAsBits(            OsConstants.CAP_BLOCK_SUSPEND,            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        );        /* 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,1032,3001,3002,3003,3006,3007",            "--capabilities=" + capabilities + "," + capabilities,            "--runtime-init",            "--nice-name=system_server",            "com.android.server.SystemServer",        };        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;    }


private static void handleSystemServerProcess(            ZygoteConnection.Arguments parsedArgs)            throws ZygoteInit.MethodAndArgsCaller {        closeServerSocket();        // set umask to 0077 so new files and directories will default to owner-only permissions.        Os.umask(S_IRWXG | S_IRWXO);        if (parsedArgs.niceName != null) {            Process.setArgV0(parsedArgs.niceName);        }        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");        if (systemServerClasspath != null) {            performSystemServerDexOpt(systemServerClasspath);        }        if (parsedArgs.invokeWith != null) {            String[] args = parsedArgs.remainingArgs;            // 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(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);            }            WrapperInit.execApplication(parsedArgs.invokeWith,                    parsedArgs.niceName, parsedArgs.targetSdkVersion,                    null, args);        } else {            ClassLoader cl = null;            if (systemServerClasspath != null) {                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());                Thread.currentThread().setContextClassLoader(cl);            }            /*             * Pass the remaining arguments to SystemServer.             */            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);        }        /* should never reach here */    }

重点是zygoteinit

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");        redirectLogStreams();        commonInit();        nativeZygoteInit();        applicationInit(targetSdkVersion, argv, classLoader);    }

这个函数都是做一些初始化工作,其中nativeZygoteInit最终会调用到app_main.cpp中的onZygoteInit

    virtual void onZygoteInit()    {        // Re-enable tracing now that we're no longer in Zygote.        atrace_set_tracing_enabled(true);        sp proc = ProcessState::self();        ALOGV("App process: starting thread pool.\n");        proc->startThreadPool();    }

applicationInit函数中的invokeStaticMain(args.startClass, args.startArgs, classLoader);最终会调用SystemServer.java中的main函数

    /**     * The main entry point from zygote.     */    public static void main(String[] args) {        new SystemServer().run();    }

关于systemserver的内容,下节再谈


更多相关文章

  1. android studio中断开SVN连接,并彻底清理项目中的.svn文件
  2. 第二十篇 Android获取本机图片、音频、视频、文档以及本地文件夹
  3. Android中资源文件用法简单示例
  4. Unity3d导出Android的apk文件时相关问题的解决办法
  5. android编译系统的makefile文件Android.mk写法
  6. android文件系统挂载分析
  7. Android 自定义文件路径选择器
  8. Android studio怎样添加assets文件

随机推荐

  1. 通过ADB命令实现App的安装、卸载、覆盖
  2. Android Inflate()方法用途
  3. Android(安卓)进阶 教你打造 Android(安
  4. Android之Rxjava2.X 10————Rxjava源
  5. Android中Calendar类的用法总结
  6. android精品开源项目整理
  7. android EditText中的几大坑
  8. Your project contains error(s)... 如何
  9. Android的历史:起源、命名方式
  10. Android 三级缓存 LruCache缓存机制