Android 創世紀 第三天

來源:互聯網
上載者:User

第三天,google說,伊甸園(linux世界)要被隔離,於是便創造了亞當(Adm)與夏娃(Eve),稱它為zygote和system_server

               --xxx

 

     第二天,init跑完了,它對於android系統,最重要的,就是啟動了zygote和system-server,誰是Adam誰是Eve?

     從分析init.rc來看

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

     --start-system-server只是個參數。

 

    分析源碼

    啊,原來夏娃(zygote)用自己的肋骨(fork)創造了亞當(system_server)!什嗎?為什麼不是亞當創造夏娃!?  android的世界,是無性繁殖的世界,zygote(夏娃)一開始就是個受精卵。。。。。。。

 

Eve誕生記(zygote啟動過程)

第一步,受精(改名)

    從init.rc可以看出,啟動的是app_process程式,啟動後,再把自己的進程名改為zygote,就算是受精了。。

 

第二步,著床(交由AppRuntime啟動javaVM)

    這時,會建立一個vm,算是android java世界的祖師爺,並且在這個vm啟動時賦予各種參數,比如我們都知道預設的情況下,一個應用程式載入的記憶體不能超過16mb,這個參數就是在這裡設定的,heapsize為16mb。這之後vm就啟動了,哦,應該叫dalvik。

    在啟動後,還會為java的類註冊JNI函數,android世界是c與java互相交織的。

第三步,生長臍帶(初涉java世界)

    註冊好各種JNI函數後,zygote的C層面就可以調用Java代碼了。

    這裡第一次進入了java世界。它調用了  com.android.internal.os.ZygoteInit 的main方法。

    java世界並不孤立

  1、它首先註冊socket,使自己成為一個服務端,也就是IPC通訊服務端。這就是android的偉大之處,巧妙利用了linux的所有特性。以後會講到zygote的真諦。

  2、然後預先載入類以及一些android資源。洋洋洒洒1k多個java類要載入,並且還都是載入時間大於1250微妙的類,android架構載入耗時的類都到這裡來載入了,這也正是android開機慢得原因,不過苦盡甘來嗎,開始累點能乾的都幹了,以後用起來就方便了,不是嗎?當然,android的系統就像是量產車,各種效能不求最好只求最穩定,廣大發燒友改rom就像改裝汽車一樣,需要精通從齒輪組到ECU的各種知識,方能達到硬體與軟體完美的結合以便發揮出最大功效,扯多了。。要想定製rom,減少開機時間,還得靠nb的水平與良好的洞察力。

  3、啟動SystemServer。也就是system_server進程。

     剛才說了,這個system_server就是Adm,夏娃的第一塊肉就這麼掉下來了,同樣利用linux的fork機制,從zygote進程分裂出了一個system_server進程。男女搭配幹活不累,亞當與夏娃共同勞動,為我們搭建美好的android世界。

     後面會分析system_server都幹些什麼事。

  4、建一個線程,轉入socket偵聽模式。每個apk在android中運行起來都是一個單獨的linux進程,這些進程,就是zygote分裂出來的。現在zygote偵聽的就是ActivityService通過system_server使用socket傳入的請求,用以分裂進程。線程之外的最後,關閉之前開啟的socket偵聽。

    現在夏娃該乾的事,基本上幹完了,就等著亞當再次讓她受精了。。。。。   -_-!!!!

 

    這裡就順便描述下每個Activity分娩出來的過程吧!(Activity大致啟動過程)

      step 1 凡人向神求仔:

           啟動一個activity,也就是startActivity。這個activity依附於一個未啟動的進程,好比剛開機,開啟一個android程式。

     step 2 大神收到祈願:

            ActvityManagerService收到startActvity,梳理一番各種參數,比如apk的報名,再將這個祈願通過送到伊甸園交由夏娃實施。

      step3 伊甸園接到生仔請求:

            亞當願意別人直接找夏娃嗎?呵呵,各種service都是SystemServer啟動起來的,而SystemServer又掌管著Binder,自己肯定會首先處理這個通知的。SystemServer通過socket這個IPC機制,向zygote發送一個fork請求,這時從java世界回到了native世界,亞當(system_server)讓夏娃(zygote)受精了。。。。 -_-!!!  android的繁榮離不開這種造仔活動

      step4 夏娃生仔:

            又要分裂了,fork出了一個新進程,並把這個進程返還給Java世界,並且由ActivityManagerService管理它。這裡,就是讓這個進程調用ActivityThread,ActvityThread就是main,apk程式的main。

            linuix中fork出來的子進程會繼承父進程的所有資訊,就相當於一個拷貝,只不過變成了另一個進程。既然繼承了所有資訊,那麼dalvik也就繼承下來了,這就解釋了為什麼一個android程式都有一個vm進程。

 

Adam誕生記(SystemServer啟動過程)

    上面提到zygote在java層啟動並fork了SystemServer,也就是夏娃身上掉下來的第一塊肉。

    SystemServer首先會關閉因fork而從父進程繼承而來的socket。

第一步,Native層初始化

     這裡會通過JNI調用native方法,又回到了Native世界。

     首先,初始化Skia引擎,就是一個映像引擎,封裝了畫圖的各種操作,這樣螢幕就能讓顯示東西了。

     然後,啟動Binder,也就是android IPC的核心。

 

第二步,換名,並進行JAVA層初始化

     換名了,這個vm進程就被正式命名為system_server了。

     java層初始化,也就是調用 com.android.server.SystemServer 的main。有趣的是,這裡通過反射,獲得SystemServer類的main方法後,不直接調用,而是拋出一個異常,這個異常包含了main這個Method。

     再回頭看看zygote的java世界,啟動了system_server的代碼是在try中,catch中就是截獲上面所說的異常,並執行main的這個Method。

 

為什麼這麼做?

先來看個樣本程式:

public class Method_test {public static void main(String[] args) {ClassA ca=new ClassA();ca.start();}}class ClassA{public ClassA() {}public void start(){System.out.println("開始調用方法");Method_A();}public void Method_A(){System.out.println("方法A被調用");Method_B();}public void Method_B(){System.out.println("方法B被調用");Method_C();}public void Method_C(){System.out.println("方法C被調用");Method_final();}public void Method_final(){System.out.println("最終方法被調用");}}

 

上面這段代碼類比一個一個情境,方法A調用B,B又調用了C。。。  A()->B()->C()->final(),final裡面可能又有更複雜的內容,而且final之後基本上不做什麼了。真實情況下,A()與final()之間還有更多的調用層次。

上面的調用棧情況是這樣的:

 

這樣的話,在一些資源稀缺的平台上,,,,的確不怎麼好,我們希望執行final的時候,前面調用的層次能消失,以前用過的變數什麼也消失,還我們一個清淨的世界,而且執行完了也不用再層層跳出了。

這時,try catch就有大作用了,看代碼:

public class Method_test {public static void main(String[] args) {ClassA ca=new ClassA();ca.start();}}class ClassA{public ClassA() {}public void start(){System.out.println("開始調用方法");try{Method_A();}catch (RuntimeException e) {//捕獲異常後再執行目標方法Method_final();}}public void Method_A(){System.out.println("方法A被調用");Method_B();}public void Method_B(){System.out.println("方法B被調用");Method_C();}public void Method_C(){System.out.println("方法C被調用");//這裡拋出一個異常throw new RuntimeException();}public void Method_final(){System.out.println("最終方法被調用");}}

與之前相比,把final()的調用換到了start()裡,直接讓c()拋出個異常,catch中執行final()。

調用棧如下:

 

Android的設計思想真猛啊,通過這麼分析,又學到一個技巧。。。。

 

     SystemService->main

         1、載入native庫並調用init1()

             這裡建立了幾個native服務, ServiceManger、SurfaceFlinger等,並把當前線程加入到Binder的通訊大軍中。

         2、通過JNI調用JAVA世界的init2()

             在上面的init1()中,最後會調用java世界的init2()。

             這裡就是啟動各種服務了,什麼EntropyService、PowerManagerService、BatteryService、WindowManager等等。

             還會把地獄犬召喚出來,也就是WatchDog(看門狗),來時刻盯著一些重要的Service,防止他們墮落。看門狗的職責就是盯著一些重要的service,萬一他們掛了,就把亞當殺死,然後讓init把它再原地滿血複活。

             最後,就進入了訊息迴圈,負責android世界中跨線程訪問的調度,google常曰 子線程要通過handler來更新UI線程,那麼handler中發送的訊息就是靠這裡來分發的。

    

這裡嚴重推薦 鄧凡平 前輩所著的《深入理解Anroid 卷I》,我自己感覺這是我見過的涉及架構的最好的一本書,主要就是通俗易懂啊(其實還是自己的水平有限)

水平有限,錯誤之處請指正,多謝!   

  創世紀:第一天串連:http://www.cnblogs.com/hangxin1940/archive/2011/10/01/2196964.html

  創世紀:第二天串連:http://www.cnblogs.com/hangxin1940/archive/2011/10/14/2196964.html

     ##第四天連結,佔位##

原創文章,轉載請說明出處:

http://www.cnblogs.com/hangxin1940/archive/2011/10/01/2196964.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.