深入了解Zygote

開門見山

所謂Zygote崖瞭,就如同它的名字“受精卵”一樣狂巢,它是Android 系統(tǒng)所有進(jìn)程的源頭,所有的進(jìn)程都是由zygote進(jìn)程fork出來的书聚。而zygote進(jìn)程是由init進(jìn)程fork出來的唧领。關(guān)于init進(jìn)程這里不做進(jìn)一步擴(kuò)展,我們只需要知道Android系統(tǒng)啟動的時候雌续,會啟動init進(jìn)程斩个,然后init進(jìn)程會創(chuàng)建zygote進(jìn)程。

Zygote 的初始化

其實(shí)zygote的初始化流程并不在zygote.java類中驯杜,而在ZygoteInit.java中受啥。我們先可以看ZygoteInit的main方法:

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        final Runnable caller;
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            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)) {
                    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.");
            }

            zygoteServer.registerServerSocketFromEnv(socketName);
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first 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();
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

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

            Zygote.nativeSecurityInit();

            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

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

            Log.i(TAG, "Accepting command socket connections");

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

雖然main方法非常的長,但是我們只關(guān)注幾個比較重要的流程

1 注冊socket

zygoteServer.registerServerSocketFromEnv(socketName);

通過這個我們可以看到鸽心,其他進(jìn)程和zygote的通訊其實(shí)就是通過socket進(jìn)行通訊的滚局,比如我們在上一篇Activity 啟動流程分析中可以看到,ActivityManagerService通知zygote fork目標(biāo)進(jìn)程就是采用的socket顽频。

2 創(chuàng)建SystemServer

 if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);

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

在這里我們可以看到藤肢,zygote其實(shí)懶的很。zygote把systemServer fork 出來后就不管了冲九,就相當(dāng)于zygote是一個大老板谤草,而systemServer是一位秘書。如果某些進(jìn)程需要和Zygote進(jìn)行通訊的時候莺奸,其實(shí)是通過SystemServer做中轉(zhuǎn)丑孩,由SystemServer和Zygote進(jìn)行通訊。
在這里灭贷,如果由同學(xué)對SystemServer的啟動流程感興趣的話温学,可以看我之前的另一篇文章 Android SystemServer 啟動流程

3開啟循環(huán)監(jiān)聽socket

caller = zygoteServer.runSelectLoop(abiList);

runSelectLoop()方法里面由一個while(true),也即是開啟一個循環(huán)不停的去監(jiān)聽當(dāng)前有沒有ZygoteConnect甚疟。

總結(jié)

Zygote分析起來其實(shí)比較簡單仗岖,結(jié)合前面的兩篇文章我們就可以把完整的流程給分析出來

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市览妖,隨后出現(xiàn)的幾起案子轧拄,更是在濱河造成了極大的恐慌,老刑警劉巖讽膏,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件檩电,死亡現(xiàn)場離奇詭異,居然都是意外死亡府树,警方通過查閱死者的電腦和手機(jī)俐末,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奄侠,“玉大人卓箫,你說我怎么就攤上這事÷⒊保” “怎么了烹卒?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長弯洗。 經(jīng)常有香客問我甫题,道長,這世上最難降的妖魔是什么涂召? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任坠非,我火速辦了婚禮,結(jié)果婚禮上果正,老公的妹妹穿的比我還像新娘炎码。我一直安慰自己,他們只是感情好秋泳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布潦闲。 她就那樣靜靜地躺著,像睡著了一般迫皱。 火紅的嫁衣襯著肌膚如雪歉闰。 梳的紋絲不亂的頭發(fā)上辖众,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音和敬,去河邊找鬼凹炸。 笑死,一個胖子當(dāng)著我的面吹牛昼弟,可吹牛的內(nèi)容都是我干的啤它。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舱痘,長吁一口氣:“原來是場噩夢啊……” “哼变骡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芭逝,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤塌碌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后旬盯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體誊爹,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年瓢捉,在試婚紗的時候發(fā)現(xiàn)自己被綠了频丘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡泡态,死狀恐怖搂漠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情某弦,我是刑警寧澤桐汤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站靶壮,受9級特大地震影響怔毛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腾降,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一拣度、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧螃壤,春花似錦抗果、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寄啼,卻和暖如春逮光,著一層夾襖步出監(jiān)牢的瞬間代箭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工涕刚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗡综,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓副女,卻偏偏與公主長得像蛤高,于是被迫代替她去往敵國和親蚣旱。 傳聞我的和親對象是個殘疾皇子碑幅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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