深入理解zygote

来源:互联网 发布:java se8 编辑:程序博客网 时间:2024/05/22 11:55
Zygote分析


zygote本身是一个native的应用程序。通过对init的解析,我们知道zygote是通过init进程根据init.rc文件中的配置项创建的,其实是通过init进程fork和execve产生的。zygote最原始的名字叫"app_process",是在其Android.mk中指定的,但是在运行过程中,将自己的名字修改成了"zygote"。

app_process对应的源文件是app_main.cpp

-->app_main.cpp(frameworks/base/cmds/app_process/app_main.cpp)int main(int argc, char* const argv[]){    /*zygote进程是由init进程fork而来,init.rc文件中为zygote进程设置的启动参数如下:service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server其中zygote是要创建的进程/system/bin/app_process是要执行的应用程序-Xzygote /system/bin --zygote --start-system-server 是传入的参数argc = 4argv = {"-Xzygote","/system/bin","--zygote","--start-system-server"}*/if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return        // EINVAL. Don't die on such kernels.        if (errno != EINVAL) {            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));            return 12;        }    }    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));    // Process command line arguments    // ignore argv[0]    argc--;    argv++;//添加虚拟机参数,结果返回0    int i;    for (i = 0; i < argc; i++) {        if (argv[i][0] != '-') {            break;        }        if (argv[i][1] == '-' && argv[i][2] == 0) {            ++i; // Skip --.            break;        }        runtime.addOption(strdup(argv[i]));    }    // Parse runtime arguments.  Stop at first unrecognized option.    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;        }    }    Vector<String8> args;    if (!className.isEmpty()) {        // We're not in zygote mode, the only argument we need to pass        // to RuntimeInit is the application argument.        //        // The Remainder of args get passed to startup class main(). Make        // copies of them before we overwrite them with the process name.        args.add(application ? String8("application") : String8("tool"));        runtime.setClassNameAndArgs(className, argc - i, argv + i);    } else {        // We're in zygote mode.        maybeCreateDalvikCache();        if (startSystemServer) {            args.add(String8("start-system-server"));        }        char prop[PROP_VALUE_MAX];        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",                ABI_LIST_PROPERTY);            return 11;        }        String8 abiFlag("--abi-list=");        abiFlag.append(prop);        args.add(abiFlag);        // In zygote mode, pass all remaining arguments to the zygote        // main() method.        for (; i < argc; ++i) {            args.add(String8(argv[i]));        }    }//就是在这里修改app_process为zygote的    if (!niceName.isEmpty()) {        runtime.setArgv0(niceName.string());        set_process_name(niceName.string());    }//调用AppRuntime的start方法    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;    }}

zygote的这个main函数比较简单,但是重要功能却是由AppRuntime完成的,接下来分析AppRuntime。
AppRuntime(frameworks/base/cmds/app_process)分析
AppRuntime继承与AndroidRuntime(/frameworks/base/core/jni),并且重载了onStarted()、onZygoteInit()、onExit()函数。前面调用了AppRuntime的start方法实际上是调用了AndroidRuntime的start()。

void AndroidRuntime::start(const char* className, const char* options){    if (!strcmp(className, "com.android.internal.os.ZygoteInit"))  {        removeHprofEmptyFile();    }    /*     * 'startSystemServer == true' means runtime is obsolete and not run from     * init.rc anymore, so we print out the boot start event here.     */    if (strcmp(options, "start-system-server") == 0) {        /* 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)));    }//如果环境变量中没有"ANDROID_ROOT",则新增该变量,并设置值为"/system"    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;//1.创建虚拟机    if (startVm(&mJavaVM, &env) != 0) {        return;    }    onVmCreated(env);    /*     * Register android functions.     *///2.注册JNI函数    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }    /*     * We want to call main() with a String array with arguments in it.     * At present we have two arguments, the class name and an option string.     * Create an array to hold them.     */    jclass stringClass;    jobjectArray strArray;    jstring classNameStr;    jstring optionsStr;    stringClass = env->FindClass("java/lang/String");    assert(stringClass != NULL);//创建一个有两个元素的string数组    strArray = env->NewObjectArray(2, stringClass, NULL);    assert(strArray != NULL);    classNameStr = env->NewStringUTF(className);    assert(classNameStr != NULL);//设置第一个元素为"com.android.internal.os.ZygoteInit"    env->SetObjectArrayElement(strArray, 0, classNameStr);    optionsStr = env->NewStringUTF(options);
<span style="white-space:pre">//设置第二个元素为"start-system-server"</span>    env->SetObjectArrayElement(strArray, 1, optionsStr);    /*     * Start VM.  This thread becomes the main thread of the VM, and will     * not return until the VM exits.     *///将com.android.internal.os.ZygoteInit转换成"com/android/internal/os/ZygoteInit"    char* slashClassName = toSlashClassName(className);    jclass startClass = env->FindClass(slashClassName);    if (startClass == NULL) {        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);        /* keep going */    } else {//找到ZygoteInit类的static main函数的JMethodId        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 {//3.通过JNI调用java函数,注意调用的函数是main,所属的类是"com.android.internal.os.ZygoteInit"//在调用了ZygoteInit的main函数之后,zygote便进入了java世界            env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0            if (env->ExceptionCheck())                threadExitUncaughtException(env);#endif        }    }    free(slashClassName);}

通过上面的分析,我们知道从native层进入java层需要关键的三个步骤:
(1)startVm
(2)startReg
(3)env->CallStaticVoidMethod(startClass, startMeth, strArray)


1.创建虚拟机-startVm

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv){//这个函数并没有什么特别的,我们只分析其中两点:/*下面代码是用来设置JNI check选项的。JNI check指的是Native层调用JNI函数时,系统会去做一些检查。*/property_get("dalvik.vm.checkjni", propBuf, "");    if (strcmp(propBuf, "true") == 0) {        checkJni = true;    } else if (strcmp(propBuf, "false") != 0) {        /* property is neither true nor false; fall back on kernel parameter */        property_get("ro.kernel.android.checkjni", propBuf, "");        if (propBuf[0] == '1') {            checkJni = true;        }    }/*     * The default starting and maximum size of the heap.  Larger     * values should be specified in a product property override.     */    strcpy(heapstartsizeOptsBuf, "-Xms");    property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");    opt.optionString = heapstartsizeOptsBuf;    mOptions.add(opt);//设置虚拟机的heapsize,默认为16M。绝大多数厂商都会修改这个值,一般为32M    strcpy(heapsizeOptsBuf, "-Xmx");    property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");    opt.optionString = heapsizeOptsBuf;    mOptions.add(opt);/*     * Initialize the VM.     *     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.     * If this call succeeds, the VM is ready, and we can start issuing     * JNI calls.     *///创建dalvik虚拟机    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {        ALOGE("JNI_CreateJavaVM failed\n");        goto bail;    }}

2.注册JNI函数-startReg
前面已经介绍了如何创建虚拟机,下一步则需要给这个虚拟机注册一些JNI函数。正是因为后续java世界用到的一些函数是native层实现的,所以才必须提前注册这些函数。

int AndroidRuntime::startReg(JNIEnv* env){    /*     * This hook causes all future threads created in this process to be     * attached to the JavaVM.  (This needs to go away in favor of JNI     * Attach calls.)     */    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);    /*     * Every "register" function calls one or more things that return     * a local reference (e.g. FindClass).  Because we haven't really     * started the VM yet, they're all getting stored in the base frame     * and never released.  Use Push/Pop to manage the storage.     */    env->PushLocalFrame(200);//注册JNI函数,gRegJNI是一个全局数组,存放需要注册的jni函数    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {        env->PopLocalFrame(NULL);        return -1;    }    env->PopLocalFrame(NULL);    //createJavaThread("fubar", quickTest, (void*) "hello");return 0;}static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env){    for (size_t i = 0; i < count; i++) {//调用数组元素的mProce方法        if (array[i].mProc(env) < 0) {            return -1;        }    }    return 0;}接下来看一下gRegJNI全局数组static const RegJNIRec gRegJNI[] = {    REG_JNI(register_com_android_internal_os_RuntimeInit),    REG_JNI(register_android_os_SystemClock),    REG_JNI(register_android_util_EventLog),    REG_JNI(register_android_util_Log),    REG_JNI(register_com_mediatek_xlog_Xlog)}

REG_JNI是一个宏,宏里边包括的就是那个mProc函数。
至此虚拟机已创建好,JNI函数已注册,下一步就是要分析CallStaticVoidMethod了,通过这个函数将从native世界进入java世界了。


根据前面的分析得知,CallStaticVoidMethod最终调用的是com.android.internal.os.ZygoteInit的main函数

-->ZygoteInit.javapublic static void main(String argv[]) {        try {            /// M: Added for BOOTPROF            //MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable"));            MTPROF_DISABLE = false;            // Start profiling the zygote initialization.            SamplingProfilerIntegration.start();            boolean startSystemServer = false;            String socketName = "zygote";            String abiList = null;//从native层传进来的参数是[com.android.internal.os.ZygoteInit,start-system-server]            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.");            }//1.注册zygote用的socket            registerZygoteSocket(socketName);            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                SystemClock.uptimeMillis());            /// M: Added for BOOTPROF            addBootEvent(new String("Zygote:Preload Start"));//2.预加载一些类和资源            preload();            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                SystemClock.uptimeMillis());            // Finish profiling the zygote initialization.            SamplingProfilerIntegration.writeZygoteSnapshot();            // Do an initial gc to clean up after startup//强制执行一次垃圾回收            gc();            // Disable tracing so that forked processes do not inherit stale tracing tags from            // Zygote.            Trace.setTracingEnabled(false);            /// M: Added for BOOTPROF            addBootEvent(new String("Zygote:Preload End"));//在这里startSystemServer为true            if (startSystemServer) {//3.开始启动system_server进程                startSystemServer(abiList, socketName);            }            Log.i(TAG, "Accepting command socket connections");//4.zygote调用这个函数            runSelectLoop(abiList);//关闭socket            closeServerSocket();        } catch (MethodAndArgsCaller caller) {//5.很重要的caller run            caller.run();        } catch (RuntimeException ex) {            Log.e(TAG, "Zygote died with exception", ex);            closeServerSocket();            throw ex;        }    }}

在ZygoteInit的main函数中,主要做了5点,下面一一分析。 

 1.注册zygote需要用的socket--registerZygoteSocket(socketName);

/** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */private static void registerZygoteSocket(String socketName) {if (sServerSocket == null) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;try {//从环境变量中获取socket的fd,这个环境变量是从init进程中通过execv传入。String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException(fullSocketName + " unset or invalid", ex);}try {//创建服务端的socket,这个socket将listen并accept clientsServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));} catch (IOException ex) {throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);}}}//注册zygote所需要的socket很简单,但是应该想谁是客户端?服务端怎么处理客户端的消息的?

2.预加载一些类和资源--preload()
|->preloadClasses()
preload()--
|->preloadResources()

-->preloadClasses()private static void preloadClasses() {        final VMRuntime runtime = VMRuntime.getRuntime();//预加载类的信息存储在PRELOADED_CLASSES中,它的值为preloaded-classes,路径在frameworks/base/preloaded-classes        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES);        if (is == null) {            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");        } else {            Log.i(TAG, "Preloading classes...");            ...... //做一些统计工作            try {                BufferedReader br = new BufferedReader(new InputStreamReader(is), 256);                String line;                while ((line = br.readLine()) != null) {                    // Skip comments and blank lines.                    line = line.trim();//按行读取,并忽略#开头的注释行                    if (line.startsWith("#") || line.equals("")) {                        continue;                    }                    try {                        if (false) {                            Log.v(TAG, "Preloading " + line + "...");                        }//通过java反射来加载类,line中存储的是预加载的类名                        Class.forName(line);                        if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {                            if (false) {                                Log.v(TAG,                                    " GC at " + Debug.getGlobalAllocSize());                            }                            System.gc();                            runtime.runFinalizationSync();                            Debug.resetGlobalAllocSize();                        }                        count++;                    } catch (ClassNotFoundException e) {                       ....                    } catch (UnsatisfiedLinkError e) {                        ....                    } catch (Throwable t) {                        ....                    }                }            } catch (IOException e) {               ....            } finally {               ....            }        }}

上述的预加载类比较简单,但是预加载这些类非常耗时,比如我现在正在做的mtk5.0项目中,这个preloaded-classes有3000行,也就是需要预加载3000个类。
preloaded-classes这个文件由frameworks/base/tools/preload工具生成,它会判断每个类加载是否超过1250微秒,如果超时则会被写入到preloaded-classes文件中,最后由zygote进行预加载。


preloadResources和preloadClasses类似,加载的是framework-res.apk中的资源。即frameworks/base/core/res/res目录下的资源。


3.开始启动system_server进程--startSystemServer(abiList, socketName)

-->startSystemServer/** * Prepare the arguments and fork for the system server process. */private static boolean startSystemServer(String abiList, String socketName)throws MethodAndArgsCaller, RuntimeException {...//设置一些参数/* 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",//进程名,叫system_server"com.android.server.SystemServer",//启动的类名};ZygoteConnection.Arguments parsedArgs = null;int pid;try {//将上述的参数数组转换成Arguments对象parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process *///fork一个子进程,这个子进程就是system_serverpid = 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 *///fork的返回值等0则表示这是子进程if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}return true;}

4.有求必应之等待请求-runSelectLoop(abiList)
当zygote从startSystemServer返回后,将会进入runSelectLoop中,在这之前registerZygoteSocket注册了一个socket,不过还没地方用到,其实主要用在runSelectLoop中。

-->runSelectLoopprivate static void runSelectLoop(String abiList) throws MethodAndArgsCaller {        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();        FileDescriptor[] fdArray = new FileDescriptor[4];//sServerSocket是之前创建的socket        fds.add(sServerSocket.getFileDescriptor());        peers.add(null);        int loopCount = GC_LOOP_COUNT;        while (true) {            int index;            if (loopCount <= 0) {                gc();                loopCount = GC_LOOP_COUNT;            } else {                loopCount--;            }            try {                fdArray = fds.toArray(fdArray);/*selectReadable内部调用select,当有客户端连接或有数据时,则selectReadable就会返回*/                index = selectReadable(fdArray);            } catch (IOException ex) {                throw new RuntimeException("Error in select()", ex);            }            if (index < 0) {                throw new RuntimeException("Error in select()");            } else if (index == 0) {//有一个客户端连接上。请注意,客户端在zygote的代表是ZygoteConnection                ZygoteConnection newPeer = acceptCommandPeer(abiList);                peers.add(newPeer);                fds.add(newPeer.getFileDescriptor());            } else {                boolean done;//客户端发送了请求,peers.get(index)返回的是ZygoteConnection,后续处理将调用ZygoteConnection的runOnce处理                done = peers.get(index).runOnce();                if (done) {                    peers.remove(index);                    fds.remove(index);                }            }        }}

runSelectLoop比较简单,即
1.处理客户端的连接和请求,其中客户端在zygote中用ZygoteConnection对象描述。
2.客户端的请求由ZygoteCoonection的runOnce()处理。


关于zygote的总结:
zygote在Android系统中创建了java世界,它创建了第一个java虚拟机,它fork出了system_server进程,zygote创建java世界的步骤:
1.创建AppRuntime对象,并调用它的start方法,实际上调用的是它的基类即AndroidRuntime的start方法。
2.创建虚拟机(startVm)、注册JNI函数(startReg)。
3.利用JNI调用java世界的ZygoteInit.java的main方法(CallStaticVoidMethod),从此进入java世界,但是这个时候java世界什么都没有。
4.在这个java世界中,调用registerZygoteSocket。通过这个函数可以响应子孙后代的请求。同时,zygote调用preloadClasses和preloadResources,为java世界添砖加瓦。
5.zygote觉得工作压力太大,就分裂出一个system_server为java世界服务。

6.zygote完成了java世界的初创,它已经很满足了。下一步就是调用runSelectLoop,等待客户端的响应了。


Zygote的时序图如下:






SystemServer分析
我们先看一下SystemServer是怎么产生的。

-->startSystemServer/** * Prepare the arguments and fork for the system server process. */private static boolean startSystemServer(String abiList, String socketName)throws MethodAndArgsCaller, RuntimeException {...//设置一些参数/* 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",//进程名,叫system_server"com.android.server.SystemServer",//启动的类名};ZygoteConnection.Arguments parsedArgs = null;int pid;try {//将上述的参数数组转换成Arguments对象parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process *///fork一个子进程,这个子进程就是system_serverpid = 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 *///fork的返回值等0则表示这是子进程if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}return true;}

从代码分析可知,system_server是通过zygote进程fork而来,forkSystemServer最终调用的native层代码:

-->dalvik_system_Zygote.cpp(这是高通平台下的,路径是/dalvik/vm/native)static void Dalvik_dalvik_system_Zygote_forkSystemServer(        const u4* args, JValue* pResult){    pid_t pid;//根据参数,fork一个子进程    pid = forkAndSpecializeCommon(args, true);    /* The zygote process checks whether the child process has died or not. */    if (pid > 0) {        int status;//保存system_server的进程id        gDvm.systemServerPid = pid;        //函数退出前先检查刚刚创建的子进程是否退出了        if (waitpid(pid, &status, WNOHANG) == pid) {            ALOGE("System server process %d has died. Restarting Zygote!", pid);//如果system_server退出了,zygote直接自杀,这是真爱            kill(getpid(), SIGKILL);        }    }    RETURN_INT(pid);}static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){    pid_t pid;    uid_t uid = (uid_t) args[0];    gid_t gid = (gid_t) args[1];    ArrayObject* gids = (ArrayObject *)args[2];    u4 debugFlags = args[3];    ArrayObject *rlimits = (ArrayObject *)args[4];    u4 mountMode = MOUNT_EXTERNAL_NONE;    int64_t permittedCapabilities, effectiveCapabilities;    char *seInfo = NULL;    char *niceName = NULL;//设置信号处理        setSignalHandler();    dvmDumpLoaderStats("zygote");//fork子进程    pid = fork();.....}接下来看一下setSignalHandlerstatic void setSignalHandler(){    int err;    struct sigaction sa;    memset(&sa, 0, sizeof(sa));    sa.sa_handler = sigchldHandler;    err = sigaction (SIGCHLD, &sa, NULL);    if (err < 0) {        ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));    }}发现调用的是sigchldHandlerstatic void sigchldHandler(int s){    pid_t pid;    int status;if (pid == gDvm.systemServerPid) {ALOG(LOG_INFO, ZYGOTE_LOG_TAG,"Exit zygote because system server (%d) has terminated",(int) pid);//如果system_server死了,zygote也要自杀了。kill(getpid(), SIGKILL);}    if (pid < 0) {        ALOG(LOG_WARN, ZYGOTE_LOG_TAG,"Zygote SIGCHLD error in waitpid: %s",strerror(errno));    }}通过代码分析,我们知道system_server和zygote真正做到了生死与共。接下来分析system_server的使命。从代码可知,system_server是从下面这几行代码开始的,if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {//关闭从Zygote那里继承下来的socketcloseServerSocket();//调用zygoteInit函数        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);}public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {//做一些常规初始化        commonInit();//1.native层的初始化        nativeZygoteInit();        applicationInit(targetSdkVersion, argv, classLoader);}private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        ....        final Arguments args;        try {            args = new Arguments(argv);        } catch (IllegalArgumentException ex) {            return;        }        // Remaining arguments are passed to the start class's static main//2.调用com.android.server.SystemServer类的main函数        invokeStaticMain(args.startClass, args.startArgs, classLoader);}

接下来分析上述两点:
1.nativeZygoteInit()

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz){//gCurRuntime即App_Runtime    gCurRuntime->onZygoteInit();}virtual void onZygoteInit(){        // Re-enable tracing now that we're no longer in Zygote.        atrace_set_tracing_enabled(true);        sp<ProcessState> proc = ProcessState::self();        ALOGV("App process: starting thread pool.\n");//启动一个线程,用于Binder通信,这样system_server就可以使用binder了        proc->startThreadPool();}

2.invokeStaticMain

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {        Class<?> cl;//这里的className是"com.android.server.SystemServer"        try {            cl = Class.forName(className, true, classLoader);        } catch (ClassNotFoundException ex) {            throw new RuntimeException("Missing class when invoking static main " + className, ex);        }        Method m;        try { //找到com.android.server.SystemServer的main方法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);        }        int modifiers = m.getModifiers();        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {            throw new RuntimeException("Main method is not public and static on " + className);        }        //抛出一个异常,为什么不直接调用main方法呢?        throw new ZygoteInit.MethodAndArgsCaller(m, argv);}上述抛出的异常是在ZygoteInit中的main函数中拦截到的,catch (MethodAndArgsCaller caller) {//5.很重要的caller run            caller.run();}public void run() {            try {//这个mMethod为com.android.server.SystemServer的main方法                mMethod.invoke(null, new Object[] { mArgs });            } catch (IllegalAccessException ex) {                ....            } }


Zygote进程fork出来的system_server进程,其实就是为了调用com.android.server.SystemServer的main函数。接下来看一下SystemServer.java的main函数。

public static void main(String[] args) {        new SystemServer().run();}private void run() {//将当前进程设置成前台进程        // Prepare the main looper thread (this thread).        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);        android.os.Process.setCanSelfBackground(false);//创建looper对象并与当前线程绑定        Looper.prepareMainLooper();//加载libandroid_servers.so        // Initialize native services.        System.loadLibrary("android_servers");//调用native Init函数        nativeInit();        // Initialize the system context.        createSystemContext();        // Create the system service manager.        mSystemServiceManager = new SystemServiceManager(mSystemContext);        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);/*这里就是system_server的主要功能了,即启动各项服务*/        // Start services.        try {            startBootstrapServices();            startCoreServices();            startOtherServices();        } catch (Throwable ex) {            .....        }        // Loop forever.        Looper.loop();}

前面说到启动system_server进程之后,就是调用runSelectLoop,等待客户端的响应了,那么谁会向zygote发送请求呢?
这里以Activity的启动为例进行分析。
ActivityManagerService发送请求,ActivityManagerService也是由system_server启动的。假设通过startActivity来启动一个Activity,那么这个Activity附属于一个未启动的进程,这个进程该如何启动?
先来看一下ActivityManagerService中的startProcessLocked函数,代码如下:

-->ActivityManagerService.javaprivate final void startProcessLocked(ProcessRecord app, String hostingType,String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {....            Process.ProcessStartResult startResult = Process.start(entryPoint,                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,                    app.info.dataDir, entryPointArgs);.....           }-->Process.javapublic static final ProcessStartResult start(final String processClass,                                  final String niceName,                                  int uid, int gid, int[] gids,                                  int debugFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String[] zygoteArgs) {        try {//调用startViaZygote            return startViaZygote(processClass, niceName, uid, gid, gids,                    debugFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, zygoteArgs);        } catch (ZygoteStartFailedEx ex) {            Log.e(LOG_TAG,                    "Starting VM process through Zygote failed");            throw new RuntimeException(                    "Starting VM process through Zygote failed", ex);        }}private static ProcessStartResult startViaZygote(final String processClass,                                  final String niceName,                                  final int uid, final int gid,                                  final int[] gids,                                  int debugFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String[] extraArgs)                                  throws ZygoteStartFailedEx {        synchronized(Process.class) {            ...//注意这里调用了openZygoteSocketIfNeeded(abi),打开了和zygote通信的socket            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);        }} private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx {        try {            final BufferedWriter writer = zygoteState.writer;            final DataInputStream inputStream = zygoteState.inputStream;            writer.write(Integer.toString(args.size()));            writer.newLine();//把请求的参数发到zygote            int sz = args.size();            for (int i = 0; i < sz; i++) {                String arg = args.get(i);                if (arg.indexOf('\n') >= 0) {                    throw new ZygoteStartFailedEx(embedded newlines not allowed");                }                writer.write(arg);                writer.newLine();            }            writer.flush();            // Should there be a timeout on this?            ProcessStartResult result = new ProcessStartResult();//读取zygote处理完的结果,便可得知是某个进程的pid            result.pid = inputStream.readInt();            if (result.pid < 0) {                throw new ZygoteStartFailedEx("fork() failed");            }            result.usingWrapper = inputStream.readBoolean();            return result;        } catch (IOException ex) {            zygoteState.close();            throw new ZygoteStartFailedEx(ex);        }}
由于ActivityManagerService驻留于system_server进程中,所以是system_server向zygote发送了消息。

根据上述代码,我们知道ActivityManagerService已经向zygote发起请求了。那么再看一下zygote是如何响应的。

-->ZygoteInit.javaprivate static void runSelectLoop(String abiList) throws MethodAndArgsCaller {try {                fdArray = fds.toArray(fdArray);                index = selectReadable(fdArray);            } catch (IOException ex) {                ...            }            else if (index == 0) {                ZygoteConnection newPeer = acceptCommandPeer(abiList);                peers.add(newPeer);                fds.add(newPeer.getFileDescriptor());            } else {                boolean done;//每当有请求时,zygote都会调用ZygoteConnection的runOnce()                done = peers.get(index).runOnce();                if (done) {                    peers.remove(index);                    fds.remove(index);                }            }}  -->ZygoteConnection.java boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {//读取system_server发送过来的参数        try {            args = readArgumentList();            descriptors = mSocket.getAncillaryFileDescriptors();        } catch (IOException ex) {            ....        }        int pid = -1;        try {//zygote又分裂出来一个子进程            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,                    parsedArgs.appDataDir);            checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");        } catch (IOException ex) {            ....        }         try {            if (pid == 0) {//子进程处理,这个子进程是不是我们需要创建的Activity的子进程呢?                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);                return true;            } else {                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);            }        }....}private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {//关闭连接的socket        closeSocket();        ZygoteInit.closeServerSocket();        if (parsedArgs.runtimeInit) {            if (parsedArgs.invokeWith != null) {                WrapperInit.execApplication(parsedArgs.invokeWith,                        parsedArgs.niceName, parsedArgs.targetSdkVersion,                        pipeFd, parsedArgs.remainingArgs);            } else {                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,                        parsedArgs.remainingArgs, null /* classLoader */);            }                }}-->RuntimeInit.javapublic static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {//做一些常规初始化        commonInit();//1.native层的初始化,最终会调用到AppRuntime的onZygoteInit,在那个函数中建立了与binder的关系        nativeZygoteInit();        applicationInit(targetSdkVersion, argv, classLoader);}private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)            throws ZygoteInit.MethodAndArgsCaller {        ....        final Arguments args;        try {            args = new Arguments(argv);        } catch (IllegalArgumentException ex) {            return;        }        // Remaining arguments are passed to the start class's static main//这里调用的是android.app.ActivityThread类的main函数        invokeStaticMain(args.startClass, args.startArgs, classLoader);}

ActivityManagerService的请求时序图如下:





0 0
原创粉丝点击