Zygote進(jìn)程的啟動源碼閱讀

本文基于Android6.0.0系統(tǒng)

從這篇文章到后面的好幾篇文章,會閱讀從Android系統(tǒng)產(chǎn)生Zygote進(jìn)程以后到我們點擊應(yīng)用圖標(biāo)啟動應(yīng)用進(jìn)程這個過程中的源碼,這個第一篇我們就來看看Zygote進(jìn)程是如何被啟動的.

我們都知道Android系統(tǒng)是基于Linux系統(tǒng)的,Linux中的所有進(jìn)程都是有init進(jìn)程fork出來的,那么Zygote進(jìn)程也不例外,他也是有init進(jìn)程fork出來的,這個我們在

\system\core\rootdir\init.zygote64.rc 文件中就可以看得到.

值得一提的是,在之前的Android源碼中init文件只有一個,現(xiàn)在的話谷歌程序員將init中的一些操作進(jìn)行了剝離,如執(zhí)行創(chuàng)建zygote進(jìn)程的代碼就分為了如下好幾個版本,這個應(yīng)該是針對不同系統(tǒng)所做出的調(diào)整.

image.png
1)我們以init.zygote32.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

這種.rc中的腳本命令的含義我們都可以在\system\core\init\readme.txt文件中找到他的含義 例如service:

Services
--------
Services are programs which init launches and (optionally) restarts
when they exit.  Services take the form of:

service <name> <pathname> [ <argument> ]*
   <option>
   <option>
   ...

1.第一句命令中的意義是 要創(chuàng)建出一個名叫 zygote 的進(jìn)程,這個進(jìn)程所要執(zhí)行的程序就在 /system/bin/app_process目錄下, -Xzygote /system/bin --zygote --start-system-server是要傳入到app_process程序中的參數(shù)

2.第三句的作用是要在上面創(chuàng)建的 zygote進(jìn)程中 啟動一個名叫 zygote 的socket,這個socket就是我們后面用作ActivityManagerService進(jìn)程和這個zygote進(jìn)程通信的,主要是請求zygote進(jìn)程fork出一個新的應(yīng)用程序進(jìn)程

3.后面的這幾句onRestart...命令都是在zygote進(jìn)程重啟時需要執(zhí)行的命令

2)后面我們確定到/system/bin/app_process對應(yīng)的文件就是 \frameworks\base\cmds\app_process\app_main.cpp文件,我們來看看app_main.cpp中都做了什么.
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {

    if (errno != EINVAL) {
        LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
        return 12;
    }
}

//創(chuàng)建AppRuntime 變量
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
argc--;
argv++;

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.
//我們傳入和參數(shù)包含  "--zygote" 和  "--start-system-server" 所以 zygote 和  startSystemServer  都會被置為true
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()) {
    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]));
    }
}

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

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.");
    return 10;
}

}

1.首先我們要明確一點的是,我們給main函數(shù)傳遞過來的參數(shù)中是 -Xzygote /system/bin --zygote --start-system-server.

2.因為參數(shù)中包含了 --zygote所以他最后會走 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);這句代碼,其實main函數(shù)中主要的工作也就是啟動創(chuàng)建AppRuntime 這個變量,而且在最后也執(zhí)行了AppRuntime的start()方法.

3)下面我們在看看AppRuntime中都做了些什么,AppRuntime也是類位于\frameworks\base\cmds\app_process\app_main.cpp文件中,我們可以發(fā)現(xiàn)他是繼承自AndroidRuntime的,而且在他里面沒有找到start()方法,所以就到他的父類AndroidRuntime中找
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
    : AndroidRuntime(argBlockStart, argBlockLength)
    , mClass(NULL){
}
.....
}
4)AndroidRuntime位于 \frameworks\base\core\jni\AndroidRuntime.cpp中,下面的代碼就是start()方法,從注釋中看,就可以看出來這個方法主要是負(fù)責(zé)啟動Android Runtime的,而且也會牽扯到調(diào)用傳入classNamemain 方法去啟動虛擬機(jī)
 /*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
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;
    //啟動虛擬機(jī)
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    //注冊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.
     */
    //將現(xiàn)有的參數(shù)轉(zhuǎn)換成ZygoteInit中main方法需要的String 數(shù)組
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * 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 {
            //調(diào)用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

1.我們先確認(rèn)一下,傳過來的參數(shù)是runtime.start("com.android.internal.os.ZygoteInit", args, zygote);這里的第三個參數(shù)zygote經(jīng)過我們的分析應(yīng)該是 true
2.這個start()方法主要做了三件事情,
??1)調(diào)用startVm()方法啟動虛擬機(jī)
??2)調(diào)用startReg()注冊了Android的JNI方法
??3)調(diào)用 env->CallStaticVoidMethod(startClass, startMeth, strArray);方法來調(diào)用ZygoteInit的main方法來啟動SystemServer進(jìn)程

5)下面我們就來看看ZygoteInit文件的main方法,該文件位于\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
        try {
            //啟動DDMS
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            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.");
            }
            
            //創(chuàng)建一個Socket用來和ActivityManagerService進(jìn)行通信
            registerZygoteSocket(socketName);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            //加載類,加載資源,加載OpenGL等
            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
            gcAndFinalize();

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

            //進(jìn)行SystemServer進(jìn)程的創(chuàng)建(fork)
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

            Log.i(TAG, "Accepting command socket connections");
            //開啟無限循環(huán)等待ActivityMangerService發(fā)送通知去fork一個新的應(yīng)用程序進(jìn)程
            runSelectLoop(abiList);

            //關(guān)閉socket
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

1.首先我們在AndroidRuntime中給ZygoteInit中傳入的參數(shù)會包含"start-system-server"所以**startSystemServer **會被置為true

2.調(diào)用 registerZygoteSocket(socketName);來創(chuàng)建一個Socket用來和ActivityManagerService進(jìn)行通信

    /**
     * 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 {
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                sServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

3.調(diào)用preload()方法去加載一些常用的類,圖片,顏色.

    static void preload() {
        Log.d(TAG, "begin preload");
        //加載Android中常用的類
        preloadClasses();
        //加載Android中常用的資源,圖片等
        preloadResources();
        //加載openGL
        preloadOpenGL();
        //加載Android中需要的一些類庫,如android,jnigraphics,compiler_rt等
        preloadSharedLibraries();
        //初始化Hyphenator(用來顯示文字)
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        //初始化WebView(在Zygote進(jìn)程中初始化是為了達(dá)到內(nèi)存共享的目的)
        WebViewFactory.prepareWebViewInZygote();
        Log.d(TAG, "end preload");
    }

4.調(diào)用 startSystemServer(abiList, socketName);來進(jìn)行fork一個新的進(jìn)程用來啟動SystemServer組件,這也就是我們說的SystemServer進(jìn)程

    /**
     * Prepare the arguments and fork for the system server process.
     */
    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,1021,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "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 */
            //新建的進(jìn)程pid會等于0
            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;
    }
  1. 調(diào)用 runSelectLoop();開啟無限循環(huán)等待ActivityMangerService發(fā)送通知去fork一個新的應(yīng)用程序進(jìn)程
        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 {
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }

6.調(diào)用RuntimeInit.enableDdms();來啟動DDMS

6)在上面第4條我們說過在創(chuàng)建SystemServer進(jìn)程的時候pid會返回0,那么后續(xù)代碼自然就會執(zhí)行handleSystemServerProcess(parsedArgs);我們一起來看看這個方法中都干了什么
 /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
      
        //因為新創(chuàng)建的進(jìn)程是在Zygote進(jìn)程中啟動的,所以該進(jìn)程也會繼承那個Socket,這里先將這個socket關(guān)閉掉
        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,
                    VMRuntime.getCurrentInstructionSet(), 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 */
    }

1.通過分析我們可以看出來這個方法是完成fork完SystemServer進(jìn)程后的其他工作

2.這個方法中最關(guān)鍵的就是** RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);**這個方法主要是去完成SystemServer進(jìn)程的啟動

7)下面我們看看RuntimeInit.zygoteInit()方法中都干了什么,RuntimeInit文件位于

\android-6.0.0_r1\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

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

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");

        //將 System.out 和 System.err 定向到Android日志中
        redirectLogStreams();

        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }

1.首先我們明確第二個參數(shù)中包含了com.android.server.SystemServer這個全類名

2.調(diào)用redirectLogStreams();方法將 System.out 和 System.err 定向到Android日志中

4.調(diào)用 commonInit();方法做時間,AndroidConfig的初始化

5.調(diào)用nativeZygoteInit();這個native方法去初始化一個Binder用來做進(jìn)程間通信

6.在 applicationInit(targetSdkVersion, argv, classLoader);中調(diào)用 invokeStaticMain(args.startClass, args.startArgs, classLoader);這個方法來調(diào)用SystemServer這個類的main方法

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {

            //調(diào)用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);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }
8)下面我們就看看nativeZygoteInit()方法中做了什么
private static final native void nativeZygoteInit();

我們可以看到他是一個native方法,它對應(yīng)的實現(xiàn)方法是在 android-6.0.0_r1\frameworks\base\core\jni\AndroidRuntime.cpp文件中

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime其實就是AndroidRuntime本身

static AndroidRuntime* gCurRuntime = NULL;

然后再去找onZygoteInit()方法,但是我們在AndroidRuntime.cpp文件中沒有找到,我們再去AndroidRuntime.h這個頭文件去找,發(fā)現(xiàn)AndroidRuntime是一個虛擬類,,所以我們需要在他的子類中找實現(xiàn)了的onZygoteInit()方法.

我們知道AppRuntime繼承了AndroidRuntime所以我們在APPRuntime中看看,他的文件對應(yīng)在android-6.0.0_r1\frameworks\base\cmds\app_process\app_main.cpp

    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

然后調(diào)用了ProcessState的startThreadPool()方法,ProcessState類位于android-6.0.0_r1\frameworks\native\libs\binder\ProcessState.cpp

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

這個方法主要是啟動一個線程池,該線程池中的線程主要是負(fù)責(zé)和binder驅(qū)動程序進(jìn)行交互的,ProcessState是Binder進(jìn)程間通信的一個基礎(chǔ)組件,這里我們就不在深究了,后面我們會仔細(xì)分析關(guān)于Android IPC的問題這里我們只需要知道nativeZygoteInit()方法就初始化了一個線程池用于和Binder基礎(chǔ)組件,這個方法執(zhí)行完后這個進(jìn)程的Binder進(jìn)程間通信基礎(chǔ)就準(zhǔn)備好了.

9)下面我們看看SystemServer中的main方法都干了什么,SystemServer位于android-6.0.0_r1\frameworks\base\services\java\com\android\server\SystemServer.java
    public static void main(String[] args) {
        new SystemServer().run();
    }

mian方法執(zhí)行完畢后SystemServer進(jìn)程就啟動了這個會在下面
SystemServer進(jìn)程啟動源碼閱讀 中分析

10)最后我們在回到5.5中,里面提到會調(diào)用ZygoteInit.runSelectLoop()方法開啟一個無限循環(huán),等待ActivityManagerService來連接這個socket然后調(diào)用ZygoteConnection.runOnce函數(shù)來創(chuàng)建新的應(yīng)用程序進(jìn)程,后面我們學(xué)習(xí)到Android啟動應(yīng)用程序的時候會仔細(xì)分析.

    /**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     *
     * @throws MethodAndArgsCaller in a child process when a main() should
     * be executed.
     */
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(sServerSocket.getFileDescriptor());
        peers.add(null);

        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 {
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }
11)到這里Zygote進(jìn)程的啟動就完成了,下面是這個流程的時序圖
zygote啟動流程.png

值得注意的點

1.Android中的進(jìn)程間通信一般是使用Binder的但是有特例就是zygote進(jìn)程和SystemServer進(jìn)程間的通信是使用Socket進(jìn)行的

2.DDMS ;Android中常用的類和資源 ;OpenGL; android,jnigraphics,compiler_rt類庫; WebView都是在ZygoteInit類中的main方法中加載的,其實WebView選擇在Zygote進(jìn)程中初始化是為了達(dá)到內(nèi)存共享的目的

3.系統(tǒng)啟動init進(jìn)程的時候在init進(jìn)程中會啟動一個Zygote進(jìn)程,Zygote進(jìn)程負(fù)責(zé)Android程序框架和其他進(jìn)程的啟動

4.Zygote進(jìn)程首先會啟動一個SystemServer進(jìn)程,該進(jìn)程用于啟動Android程序中的各種服務(wù),如PackageManagerService等

5.當(dāng)我們需要新建一個應(yīng)用程序進(jìn)程時ActivityManagerService會通過socket進(jìn)程間通信,通知Zygote去新建一個進(jìn)程.

6.在AndroidRuntime的main方法中啟動了虛擬機(jī),注冊了JNI方法

7.Zygote進(jìn)程在Linux解析init.zygote32.rc中的 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
這句代碼的餓時候就已經(jīng)創(chuàng)建了,后面執(zhí)行的/system/bin/app_process中的代碼都是在該進(jìn)程中執(zhí)行的

參考文章

http://blog.csdn.net/luoshengyang/article/details/6768304
http://blog.csdn.net/qq_23547831/article/details/51104873

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖屁置,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡材失,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門硫豆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龙巨,“玉大人,你說我怎么就攤上這事熊响≈急穑” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵汗茄,是天一觀的道長秸弛。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么递览? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任叼屠,我火速辦了婚禮,結(jié)果婚禮上绞铃,老公的妹妹穿的比我還像新娘镜雨。我一直安慰自己,他們只是感情好儿捧,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布荚坞。 她就那樣靜靜地躺著,像睡著了一般纯命。 火紅的嫁衣襯著肌膚如雪西剥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天亿汞,我揣著相機(jī)與錄音瞭空,去河邊找鬼。 笑死疗我,一個胖子當(dāng)著我的面吹牛咆畏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吴裤,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼旧找,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了麦牺?” 一聲冷哼從身側(cè)響起钮蛛,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剖膳,沒想到半個月后魏颓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡吱晒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年甸饱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仑濒。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡叹话,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出墩瞳,到底是詐尸還是另有隱情驼壶,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布喉酌,位于F島的核電站辅柴,受9級特大地震影響箩溃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碌嘀,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望歪架。 院中可真熱鬧股冗,春花似錦、人聲如沸和蚪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攒霹。三九已至怯疤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間催束,已是汗流浹背集峦。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留抠刺,地道東北人塔淤。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像速妖,于是被迫代替她去往敵國和親高蜂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容