Android源碼(1) --- Zygote進(jìn)程啟動(dòng)流程

Zygote進(jìn)程簡(jiǎn)介

什么是Zygote進(jìn)程? Zygote進(jìn)程 是整個(gè)Android系統(tǒng)的根進(jìn)程力九,包括SystemServer進(jìn)程和所有應(yīng)用進(jìn)程在內(nèi)都是通過Zygote進(jìn)程 fork 出來的谍倦。Zygote進(jìn)程則是通過Linux系統(tǒng)init進(jìn)程啟動(dòng)塞赂。

  • 啟動(dòng)順序: Linux系統(tǒng)init進(jìn)程 --> Zygote進(jìn)程 --> SystemServer進(jìn)程 --> Application 進(jìn)程
  • init進(jìn)程:Android系統(tǒng)第一個(gè)進(jìn)程,也是linux的根進(jìn)程昼蛀,主要用于初始化各種文件系統(tǒng)宴猾,輸入輸出系統(tǒng),log系統(tǒng)等等設(shè)備相關(guān)聯(lián)的初始化
  • Zygote進(jìn)程:Android系統(tǒng)的根進(jìn)城叼旋,用于fork除SystemServer進(jìn)程和各種應(yīng)用進(jìn)程
  • SystemServer進(jìn)程 --> 啟動(dòng)ActivityManagerService,WindowManagerService,PowerManagerService等等各項(xiàng)服務(wù)
  • Application 進(jìn)程: App 應(yīng)用進(jìn)程

源碼分析(Android 6.0)

  • 1.從ZygoteInit main()方法中開始看仇哆。
  public static void main(String argv[]) {
        try {
            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.");
            }

            registerZygoteSocket(socketName);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            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);

            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }

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

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

  • 從上面可以看到主要做了哪幾件事

    • 1.1 enableDdms() 設(shè)置DDMS可用

    • 1.2 for 循環(huán),解析是否需要啟動(dòng)SystemService進(jìn)程夫植;獲取abi列表讹剔;獲取socket連接名稱

    • 1.3 registerZygoteSocket(String socketName) 為Zygote 進(jìn)程注冊(cè)socket;(PS:Android中進(jìn)程間通都是用Binder,但是有一個(gè)例外,SystemService進(jìn)程與Zygote進(jìn)程之間是通過Socket的方式進(jìn)行通訊的)

       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);
              }
          }
      }
      
    • 1.4 preload(),可以看到
      preloadClasses 初始化Zygote所需的類
      preloadResources 初始化通用系統(tǒng)資源
      preloadOpenGL 初始化OpenGL
      preloadSharedLibraries 初始化 shared libraries
      preloadTextResources 初始化文字資源
      prepareWebViewInZygote 初始化WebView(必須是Zygote進(jìn)程)

      static void preload() {
              Log.d(TAG, "begin preload");
              preloadClasses();
              preloadResources();
              preloadOpenGL();
              preloadSharedLibraries();
              preloadTextResources();
              // Ask the WebViewFactory to do any initialization that must run in the zygote process,
              // for memory sharing purposes.
              WebViewFactory.prepareWebViewInZygote();
              Log.d(TAG, "end preload");
          }
      
    • 1.5 SamplingProfilerIntegration.writeZygoteSnapshot() 存儲(chǔ)一下zygote進(jìn)程快照
      gcAndFinalize() fork之前調(diào)用下系統(tǒng)GC

    • 1.6 startSystemServer(abiList, socketName)辟拷,接下來就是fork SystemServer進(jìn)程了
      通過Zygote.forkSystemServe() fork 出SystemServer進(jìn)程

    • 1.7 關(guān)閉Socket
      handleSystemServerProcess 當(dāng)fork出SystemServer后關(guān)閉socket

    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 */
                            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;
                    }
    
    
        /**
         * Finish remaining work for the newly forked system server process.
         */
        private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws ZygoteInit.MethodAndArgsCaller {
    
            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 */
        }
    

### 梳理一下流程
![流程圖](https://github.com/jfson/ImgResource/blob/master/13.png?raw=true)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撞羽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子衫冻,更是在濱河造成了極大的恐慌诀紊,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隅俘,死亡現(xiàn)場(chǎng)離奇詭異邻奠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)为居,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門碌宴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蒙畴,你說我怎么就攤上這事贰镣。” “怎么了膳凝?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵碑隆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蹬音,道長(zhǎng)上煤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任著淆,我火速辦了婚禮劫狠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘永部。我一直安慰自己独泞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布苔埋。 她就那樣靜靜地躺著阐肤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪讲坎。 梳的紋絲不亂的頭發(fā)上孕惜,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音晨炕,去河邊找鬼衫画。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瓮栗,可吹牛的內(nèi)容都是我干的削罩。 我是一名探鬼主播瞄勾,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼弥激!你這毒婦竟也來了进陡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤微服,失蹤者是張志新(化名)和其女友劉穎趾疚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體以蕴,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糙麦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丛肮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赡磅。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宝与,靈堂內(nèi)的尸體忽然破棺而出焚廊,到底是詐尸還是另有隱情,我是刑警寧澤习劫,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布节值,位于F島的核電站,受9級(jí)特大地震影響榜聂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗓蘑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一须肆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桩皿,春花似錦豌汇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佛嬉,卻和暖如春逻澳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暖呕。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工斜做, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人湾揽。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓瓤逼,卻偏偏與公主長(zhǎng)得像笼吟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霸旗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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