Android 進(jìn)程啟動流程總結(jié)

Android 中所有應(yīng)用的進(jìn)程都是從 Zygote 分裂出來的,而進(jìn)程也是承載各種應(yīng)用埋合、服務(wù)的基礎(chǔ)备徐,所以啟動任何的服務(wù)和應(yīng)用的第一步就是創(chuàng)建一個進(jìn)程。
上一篇 介紹了 Zygote 啟動后開啟了一個 socket 等待處理客戶端的請求甚颂,本文就主要介紹 AMS 通過 socket 請求 Zygote 創(chuàng)建進(jìn)程的過程

1 AMS.startProcessLocked

當(dāng)啟動一個應(yīng)用時蜜猾,首先需要創(chuàng)建這個應(yīng)用對應(yīng)的進(jìn)程秀菱。具體是怎樣走到 AMS.startProcessLocked 這一步的,需要單獨(dú)一篇文章來介紹蹭睡,簡單的說衍菱,當(dāng)我們調(diào)用 startActivity 啟動一個應(yīng)用時,最終就會調(diào)用到AMS.startProcessLocked 這一步肩豁。注意脊串,AMS 是在 SystemServer 進(jìn)程中執(zhí)行,Android 系統(tǒng)啟動流程總結(jié) 第4節(jié)有介紹清钥,最終在 SystemServer 進(jìn)程中啟動了 AMS洪规。
startProcessLocked() 這個方法看起來很長,其實關(guān)鍵的就這一句

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.start
-> ZygoteProcess.start
-> ZygoteProcess.startViaZygote
-> ZygoteProcess.zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)
(ZygotePorcess.ZygoteState 這個內(nèi)部類循捺,負(fù)責(zé)與 Zygote 建立 socket 連接)
經(jīng)過層層調(diào)用斩例,最終 zygoteSendArgsAndGetResult 就通過 ZygoteState 把一堆參數(shù)發(fā)給 Zygote,接下來就是看 Zygote 的處理

2. Zygote 處理請求

Zygote在啟動之后从橘,調(diào)用 ZygoteServer.runSelectLoop 進(jìn)入等待請求的死循環(huán)中:

void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(mServerSocket.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); // 1. 阻塞在這一步念赶,直到收到連接請求
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce(this); // 2. 收到請求后再循環(huán)一次進(jìn)入該執(zhí)行分支
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

    private ZygoteConnection acceptCommandPeer(String abiList) {
        try {
            return createNewConnection(mServerSocket.accept(), abiList);
        } catch (IOException ex) {
            throw new RuntimeException(
                    "IOException during accept()", ex);
        }
    }

    protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
            throws IOException {
        return new ZygoteConnection(socket, abiList);
    }

mServerSocket 是一個 LocalServerSocket 對象,其 accept() 方法會一直租塞直到有收到連接請求恰力,之后創(chuàng)建一個 ZygoteConnection叉谜,然后再一輪 while 循環(huán)就進(jìn)入到注釋2處的執(zhí)行分支,調(diào)用 ZygoteConnection.runOnce 方法踩萎。

ZygoteConnection.runOnce()

ZygoteConnection 中保存了一個 socket 對象停局,從中讀取解析請求參數(shù)后,最終調(diào)用 Zygote.forkAndSpecialize 創(chuàng)建出了新的進(jìn)程香府,之后分兩路分別調(diào)用 handleChildProc() 和 handleParentProc() 處理子進(jìn)程和 Zygote 進(jìn)程董栽。

  • handleChildProc() 中的邏輯和 Android 系統(tǒng)啟動流程總結(jié) 中第3節(jié)介紹 SystemServer 的啟動很像,也是進(jìn)入 RuntimeInit.zygoteInit()企孩,最終通過拋異常的方法調(diào)用對應(yīng) Java 類的 mian() 函數(shù)锭碳,如果是啟動應(yīng)用或者服務(wù),這里的 Java 類就是 ActivityThread
  • handleParentProc() 進(jìn)行一些清理工作勿璃,不是本文的重點(diǎn)擒抛,略。
最后編輯于
?著作權(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)容