Zygote的啟動流程

2021-01-10 Android系統實戰開發

前言

Android系統開發,zygote顯然是接觸很多的一個術語。那zygote是什麼呢?好奇查了下zygote的中文翻譯:受精卵。這是我見過最形象和最正確的命名。顧名思義,就是孵化下一代。Android中,Zygote是所有App的父進程,所有的app都由它孵化而出,可見zygote的地位,堪比女媧造人。那zygote在Android系統中是如何啟動的呢?

概述

眾所周知,Android系統是跑在Linux內核上的,姑且將zygote看成是跑在Linux上的一個Linux應用。那麼zygote想要啟動,則必然需要先讓Linux內核跑起來(聽起來像是廢話了~)。事實也是如此,zygote正是由Linux的天字第一號進程【init】啟動。接下來就是從init.rc開始,一路分析zygote的啟動過程。先上一張流程圖,本文所講的內容都在這。

init.rc

init進程啟動後,對init.rc文件進行了解析並執行了各個階段的動作,而zygote進程就是這個過程中被觸發啟動的。直接看代碼直觀點:

/system/core/rootdir/init.rcon late-init ... # Now we can start zygote for devices with file based encryption trigger zygote-start...on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted start netd start zygote start zygote_secondary ...zygote在init.rc中被觸發並通過【start zygote】的方式啟動,而這裡的zygote是init.rc文件中的服務,如下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasks可見zygote服務最終調用了app_process這個可執行文件,並傳入【–zygote】和【–start-system-server】這兩個參數。

app_main

app_main是一個可執行文件,入口是main函數,具體源碼如下:

/frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ... 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; } } ... if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } ... }專注zygote相關的關鍵代碼,在這個main函數中,主要做了三件事:

1.使用AppRuntime類實例化了一個虛擬機runtime,而AppRuntime則繼承AndroidRuntime;2.解析傳給app_main的參數,主要是zygote和start_system_server;3.啟動虛擬機。啟動的方法start是父類AndroidRuntime的方法。注意第一個傳參的參數。zygote啟動方法在AndroidRuntime中,進入觀摩下。

AndroidRuntime

frameworks/base/core/jni/AndroidRuntime.cppvoid AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){ ... JniInvocation jni_invocation; jni_invocation.Init(NULL); //加載libart.so JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); /* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ... char* slashClassName = toSlashClassName(className != NULL ? 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); } } ...}start方法中,主要做了四件事:

1.加載libart.so,否則不能啟動虛擬機;2.啟動虛擬機;3.加載註冊JNI方法;4.根據傳遞給start方法的第一個參數,去尋找ZygoteInit類,找到類之後,找到該類的main方法,然後調用,在這之後就進入了Java的世界。start方法的第一個參數為"com.android.internal.os.ZygoteInit",然後通過FindClass方法找到ZygoteInit類,然後再調用相應的main方法進入到Java世界。

ZygoteInit

到了這裡,就已經進入到了Java的世界,虛擬機已經運行起來,接下來要做的事就是啟動system_server,然後做好自己的本分,等待孵化app的指令。具體詳見main方法:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.javapublic static void main(String argv[]) { ... 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); if (caller != null) { caller.run(); } ...}主要做了三件事:

1.解析參數;2.fork system_server;3.調用runSelectLoop方法,等待進程孵化請求;每個main方法一定會做的事情,那就是解析傳入給它的參數,這裡主要解析了start_system_server的創建需求,這個參數是從init.rc中傳下來的。如果init.rc中有創建的system_server的需求,那麼就會在這裡被解析,然後進行創建。zygote在完成了system_server的創建後,調用runSelectLoop方法進行等待,響應app進程的創建請求,創建成功後,再調用run方法執行。

結語

zygote的啟動分析到此結束,到了這裡,zygote就一直等待進程的創建請求,app想要啟動的時候,就由ams通過socket發需求給zygote就好。

每一次的源碼閱讀,都有種【自己很渺小】的感覺。對自己來講,對Android源碼的每一次閱讀,就是一次揭秘的過程。但每一次閱讀完,都會產生新的疑問,比如app的啟動流程是怎麼樣的?ams又是跟zygote怎樣創建聯繫的?

但正是這些疑問驅使我去閱讀源碼,去了解箇中奧妙。

相關焦點

  • 柴油發電機組操作流程及不能啟動的原因
    柴油發電機組操作流程及不能啟動的原因
  • 【原色動態】原色諮詢與中集物流啟動業務流程標準化合作
    2020年12月,中集物流業務流程標準化項目正式啟動。中集物流基於自身業務發展和公司的管理要求,與原色諮詢團隊合作,成立業務流程標準化項目組:聚焦中集物流的流程管理體系搭建和核心業務流程梳理,搭建中集物流標準化運作的流程能力基礎,為後續業務運營整合和業務擴張做好準備。
  • 河南中小學教師資格面試報名12月10日啟動!流程及注意事項發布
    河南中小學教師資格面試報名12月10日啟動!流程及注意事項發布 2020-12-03 18:42 來源:澎湃新聞·澎湃號·媒體
  • 登鑽井平臺觀造船流程,臨港新片區啟動首批6條工業旅遊線路
    登鑽井平臺觀造船流程,臨港新片區啟動首批6條工業旅遊線路 澎湃新聞記者 張靜 2020-07-30 18:55 來源:
  • 針對進境航班出現多起輸入病例 上海市進一步嚴格全流程閉環管理,相關部門已啟動熔斷機制
    來源:上海發布 針對近期部分進境航班連續出現多起輸入病例的情況,上海市新冠肺炎疫情防控工作領導小組辦公室表示,將進一步嚴格全流程閉環管理,嚴格落實各項健康管理措施,督促相關企業切實落實主體責任,抓好源頭和遠端防控,堅決遏制境外疫情輸入。據悉,民航部門已經依照程序啟動對相關航班的熔斷機制。
  • 河南中小學教師資格面試報名12月10日啟動(附流程及注意事項)
    河南省2020年下半年中小學教師資格考試面試網上報名定於12月10日啟動,政策明確,報名資格審查貫穿教師資格考試、認定的全過程,若在審核、面試階段發現考生重要信息存在虛假填報或填報不實,將會被取消「報名資格」或「考試成績」。
  • 既然啟動流程不太了解,那你知道Tomcat的生命周期是什麼樣子的麼?
    啟動的時候的大家可以隨便找一個zip版本的Tomcat,然後直接啟動起來,我們來看看是個什麼樣子的,一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init 信息: Initializing ProtocolHandler ["http-bio-8080
  • 哈醫大二院啟動腫瘤內科「日間病房」 簡化就醫流程降低住院費用
    近日,為切實解決腫瘤患者的住院難題,縮短等候時間,簡化就醫流程,降低住院費用,並為患者提供安全有效的治療,哈醫大二院正式啟動腫瘤內科「日間病房」。
  • 大姚縣疊螺式汙泥脫水機檢修流程
    大姚縣疊螺式汙泥脫水機檢修流程 ,「w2se3」  宜興市森諾特環保是生產疊螺式汙泥脫水機、疊螺汙泥脫水機和疊螺式汙泥脫水機的疊螺式汙泥脫水機廠家,歡迎廣大客戶前來參觀考察,共同為環保事業做一份貢獻。
  • 一文詳解:包裝紙箱製作工藝,紙箱製作流程,紙箱定做流程
    機械【紙盒包裝製作】包裝紙箱製作工藝 紙箱製作流程 紙箱定做流程 紙箱材質構成 面紙的介紹 造紙基本生產工藝流程 什麼是瓦楞紙 紙箱印刷技術 水印紙箱生產流程 油印紙箱生產流程 性能測試必須對所有試樣進行前處理。
  • 趣味問題:汽車怎樣啟動才不傷車,ON檔需要停留嗎?
    #老司機聊汽車知識#內容概述:啟動系統與電瓶的關係啟動流程與油泵的關係正常啟動與異常啟動的區別汽車啟動發動機是否有必要按照「三步驟」操作,一鍵啟動應當如何操作才不傷車;這倆問題困擾了很多新手司機,其實大可不必有什麼擔心——如果「傷車」的標準代表故障的話,怎樣啟動都不會因其故障,只是對於電瓶使用壽命會有些許的影響罷了,然而只要對電瓶的用時沒有非常高的要求則沒有任何需要顧慮
  • 點火系統電氣原理圖,啟動線路分析,面對啟動故障,不用怕啦!
    點火系統電氣原理圖,啟動線路分析,面對啟動故障,不用怕啦!以挖機為例:啟動線路,負極開關,鑰匙開關,蓄電池,起動機,發電機以及保險、繼電器和二極體等組成。: X88/6 X4/30 繼電器K2的端子30與87a- X4/34-啟動機M2的端子50啟動機M2的端子30和50均與30號正極線接通,保證工作條件,此時啟動機工作, 發動機工作, 發電機G3發電2.3 鬆開點火開關S3,自動回到O位,此時通過發電機G3發出的電, D+-K3的端子85使K3停 作 止工作, K3的端子30與87a
  • 燃油動力汽車啟動系統知識普及:啟動原理/冷啟動/原地熱車概念
    說明:解析這一問題需要基於發動機「啟動系統」的機械原理,在掌握啟動原理的知識後,對於很多依靠經驗積累的錯誤用車知識會有顛覆性的認知。比如高頻率啟動發動機的影響,啟動失敗是否會傷車,啟動後是否需要原地熱車,啟動會後應該如何正常駕駛車輛才能起到「保養作用」等,下面從基礎的啟動原理開始講解。
  • 《光環4》圖文全劇情流程攻略 Halo4全任務流程攻略
    《光環4》圖文全劇情流程攻略,Halo4全任務流程攻略(含「通關劇情流程」「主/支線任務」)。《光環4》是一款動作角色扮演遊戲,是光環系列的第四部正篇續作。趕緊去啟動重力裝置吧,之後不需要戰鬥,按住衝刺鍵跑,在最短的時間內衝刺到控制臺,無奈,還是晚了一步,飛船解體,你被碎片擊暈,章節結束。
  • 組織診斷與團隊診斷輔導活動的關鍵流程
    組織診斷與團隊診斷輔導活動的關鍵流程組織診斷業界的定義:諮詢顧問、研究人員或管理人員運用概念化的模型和實用的研究方法評估一個組織當前的狀況,找到解決問題的方法,迎接挑戰,提高績效。三、團隊診斷與輔導活動的關鍵流程團隊診斷與輔導活動的關鍵流程1、啟動目標:找到適當的切入點,激發團隊主管重視和支持。
  • 圖文解析 | 螺杆空壓機換油流程10步法
    為規範空壓機換油流程,本文用圖文形式做一簡要介紹,以供行業從業者參考。換油流程總要求內部結構嚴格遵守空壓機潤滑油推薦使用周期嚴格遵守空壓機潤滑油換油流程,儘可能放盡舊油,防止新油受到汙染,造成不必要的問題。在更換油品的同時必須同時更換相關備件,包括空濾、油濾等。對於發生結膠的機器,必須進行徹底清理,並執行衝洗操作。準備工作在空壓機維保前,需要準備好所需工具,包括:安全防護工具、拆卸工具、換油工具和備件備品。
  • 看華為人如何實踐流程變革:流程變革如何更好支撐業務穩健成長?
    流程的本質是什麼?流程為誰而變?管理者該如何從業務中萃取流程DNA? 局部流程優化該從何入手?流程該何時變革? 廣為大家熟知或道聽途說的IPD項目背後,優秀的華為質量經理人究竟如何所思所想?做對了什麼?流程制度建設是如何強有了的支撐華為持續業績增長的?