Android 開篇

alleyway 7年前發布 | 7K 次閱讀 安卓開發 Android開發 移動開發

一、引言

Android系統非常龐大、錯中復雜,其底層是采用Linux作為基底,上層采用包含虛擬機的Java層以及Native層,通過系統調用(Syscall)連通系統的內核空間與用戶空間。用戶空間主要采用C++和Java代碼,通過JNI技術打通用戶空間的Java層和Native層(C++/C),從而融為一體。

Google官方提供了一張經典的四層架構圖,從下往上依次分為Linux內核、系統庫和Android運行時環境、框架層以及應用層這4層架構,其中每一層都包含大量的子模塊或子系統。這只是如壘磚般地分層,并沒有表達Android整個系統的內部架構、運行機理,以及各個模塊之間是如何銜接與配合工作的。 為了更深入地掌握Android整個架構思想以及各個模塊在Android系統所處的地位與價值,計劃以Android系統啟動過程為主線,以進程的視角來詮釋Android M系統全貌 ,全方位的深度剖析各個模塊功能,爭取各個擊破。這樣才能猶如庖丁解牛,解決、分析問題則能游刃有余。

二、Android架構

Google提供的4層架構圖很經典,但為了更進一步透視Android系統架構,本文更多的是以進程的視角,以分層的架構來詮釋Android系統的全貌,闡述Android內部的環環相扣的內在聯系。

系統啟動架構圖

點擊查看大圖

圖解:Android系統啟動過程由上圖從下往上的一個過程: Loader -> Kernel -> Native -> Framework -> App ,接來下簡要說說每個過程:

2.1 Loader層

  • Boot ROM: 當手機處于關機狀態時,長按Power鍵開機,引導芯片開始從固化在 ROM 里的預設出代碼開始執行,然后加載引導程序到 RAM ;
  • Boot Loader:這是啟動Android系統之前的引導程序,主要是檢查RAM,初始化硬件參數等功能。

2.2 Kernel層

Kernel層是指Android內核層,到這里才剛剛開始進入Android系統。

  • 啟動Kernel的swapper進程(pid=0):該進程又稱為idle進程, 系統初始化過程Kernel由無到有開創的第一個進程, 用于初始化進程管理、內存管理,加載Display,Camera Driver,Binder Driver等相關工作;
  • 啟動kthreadd進程(pid=2):是Linux系統的內核進程,會創建內核工作線程kworkder,軟中斷線程ksoftirqd,thermal等內核守護進程。 kthreadd進程是所有內核進程的鼻祖 。

2.3 Native層

這里的Native層主要包括init孵化來的用戶空間的守護進程、HAL層以及開機動畫等。啟動init進程(pid=1),是Linux系統的用戶進程, init進程是所有用戶進程的鼻祖 。

  • init進程會孵化出ueventd、logd、healthd、installd、adbd、lmkd等用戶守護進程;
  • init進程還啟動 servicemanager (binder服務管家)、 bootanim (開機動畫)等重要服務
  • init進程孵化出Zygote進程,Zygote進程是Android系統的第一個Java進程, Zygote是所有Java進程的父進程 ,Zygote進程本身是由init進程孵化而來的。

2.4 Framework層

  • Zygote進程,是由init進程通過解析init.rc文件后fork生成的,Zygote進程主要包含:
    • 加載ZygoteInit類,注冊Zygote Socket服務端套接字;
    • 加載虛擬機;
    • preloadClasses;
    • preloadResouces。
    </li>
  • System Server進程,是由Zygote進程fork而來, System Server是Zygote孵化的第一個進程 ,System Server負責啟動和管理整個Java framework,包含ActivityManager,PowerManager等服務。
  • Media Server進程,是由init進程fork而來,負責啟動和管理整個C++ framework,包含AudioFlinger,Camera Service,等服務。
  • </ul>

    2.5 App層

    • Zygote進程孵化出的第一個App進程是Launcher,這是用戶看到的桌面App;
    • Zygote進程還會創建Browser,Phone,Email等App進程,每個App至少運行在一個進程上。
    • 所有的App進程都是由Zygote進程fork生成的。

    2.6 Syscall && JNI

    • Native與Kernel之間有一層系統調用(SysCall)層,
    • Java層與Native(C/C++)層之間的紐帶JNI,見Android JNI原理分析。

    三、通信方式

    無論是Android系統,還是各種Linux衍生系統,各個組件、模塊往往運行在各種不同的進程和線程內,這里就必然涉及進程/線程之間的通信。對于IPC(Inter-Process Communication, 進程間通信),Linux現有管道、消息隊列、共享內存、套接字、信號量、信號這些IPC機制,Android額外還有Binder IPC機制,Android OS中的Zygote進程的IPC采用的是Socket機制,在上層system server、media server以及上層App之間更多的是采用Binder IPC方式來完成跨進程間的通信。對于Android上層架構中,還多時候是在同一個進程的線程之間需要相互通信,例如同一個進程的主線程與工作線程之間的通信,往往采用的Handler消息機制。

    想深入理解Android內核層架構,必須先深入理解Linux現有的IPC機制;對于Android上層架構,則最常用的通信方式是Binder、Socket、Handler,當然也有少量其他的IPC方式,比如殺進程Process.killProcess()采用的是signal方式。下面說說Binder、Socket、Handler:

    3.1 Binder

    Binder作為Android系統提供的一種IPC機制,無論從系統開發還是應用開發,都是Android系統中最重要的組成,也是最難理解的一塊知識點,想了解 為什么Android要采用Binder作為IPC機制? 可查看我在知乎上的回答。深入了解Binder機制,最好的方法便是閱讀源碼,借用Linux鼻祖Linus Torvalds曾說過的一句話:Read The Fucking Source Code。下面簡要說說Binder IPC原理。

    Binder IPC原理

    Binder通信采用c/s架構,從組件視角來說,包含Client、Server、ServiceManager以及binder驅動,其中ServiceManager用于管理系統中的各種服務。

    • 想進一步了解Binder,可查看Binder系列—開篇,Binder系列花費了13篇文章的篇幅,從源碼角度出發來,講述Driver、Native、Framework、App四個層面的整個完整流程。根據有些讀者反饋這個系列還是不好理解,這個binder涉及的層次跨度比較大,知識量比較廣, 建議大家先知道binder是用于進程間通信,有個大致概念就可以.先去學習系統基本知識,等后面有一定功力再進一步深入研究Binder.

    Native層面:

    Driver層面:

    Framework層面:

    App層面

    全棧架構型:從Java framework到Native層,再到Linux層的一條線的串通

    3.2 Socket

    Socket通信方式也是C/S架構,比Binder簡單很多。在Android系統中采用Socket通信方式的主要:

    • zygote:用于孵化進程,系統進程system_server孵化進程時便通過socket向zygote進程發起請求;
    • installd:用于安裝App的守護進程,上層PackageManagerService很多實現最終都是交給它來完成;
    • lmkd:lowmemorykiller的守護進程,Java層的LowMemoryKiller最終都是由lmkd來完成;
    • adbd:這個也不用說,用于服務adb;
    • logcatd:這個不用說,用于服務logcat;
    • vold:即volume Daemon,是存儲類的守護進程,用于負責如USB、Sdcard等存儲設備的事件處理。

    等等還有很多,這里不一一列舉,Socket方式更多的用于Android framework層與native層之間的通信。Socket通信方式相對于binder非常簡單,所以一直沒有寫相關文章,為了成一個體系,下次再補上。

    3.3 Handler

    Binder/Socket用于進程間通信,而Handler消息機制用于同進程的線程間通信,Handler消息機制是由一組MessageQueue、Message、Looper、Handler共同組成的,為了方便且稱之為Handler消息機制。

    有人可能會疑惑,為何Binder/Socket用于進程間通信,能否用于線程間通信呢?答案是肯定,對于兩個具有獨立地址空間的進程通信都可以,當然也能用于共享內存空間的兩個線程間通信,這就好比殺雞用牛刀。接著可能還有人會疑惑,那handler消息機制能否用于進程間通信?答案是不能,Handler只能用于共享內存地址空間的兩個線程間通信,即同進程的兩個線程間通信。很多時候,Handler是工作線程向UI主線程發送消息,即App應用中只有主線程能更新UI,其他工作線程往往是完成相應工作后,通過Handler告知主線程需要做出相應地UI更新操作,Handler分發相應的消息給UI主線程去完成,如下圖:

    由于工作線程與主線程共享地址空間,即Handler實例對象 mHandler 位于線程間共享的內存堆上,工作線程與主線程都能直接使用該對象,只需要注意多線程的同步問題。工作線程通過 mHandler 向其成員變量 MessageQueue 中添加新Message,主線程一直處于loop()方法內,當收到新的Message時按照一定規則分發給相應的 handleMessage ()方法來處理。所以說,而Handler消息機制用于同進程的線程間通信的核心是線程間共享內存空間,而不同進程擁有不同的地址空間,也就不能用handler來實現進程間通信。

    上圖只是Handler消息機制的一種處理流程,是不是只能工作線程向UI主線程發消息呢,其實不然,可以是UI線程想工作線程發送消息,也可以是多個工作線程之間通過handler發送消息。更多關于Handler消息機制文章:

    要理解framework層源碼,掌握這3種基本的進程/線程間通信方式是非常有必要,當然Linux還有不少其他的IPC機制,比如共享內存、信號、信號量,在源碼中也有體現,如果想全面徹底地掌握Android系統,還是需要對每一種IPCd機制都有所了解。

    四、計劃提綱

    2016年新的一年剛開始,首先祝大家、也祝自己在新的一年諸事順心,事業蒸蒸日上。在過去的一年,對于Android從底層一路到上層有不少自己的理解和沉淀,但總體較零散,未成體系。借著今天(元旦假日的最后一天),給自己的新的一年提前做一個計劃,把知識進行歸檔整理與再學習,從而加深對Android架構的理解。通過前面對系統啟動的介紹,相信大家對Android系統有了一個整體觀,接下來需要抓核心、理思路,爭取各個擊破。

    計劃:不少文章還沒來得及進一步加工,大篇章的源碼,有讀者跟我反饋看著發困,先別急,文章還會不斷更新和升級。前期計劃先將系統所有核心技術點的邊整理邊寫博客;后期工作有時間再根據大家的反饋以及自己的校驗,再不斷修正和完善所有文章,爭取給文章,再進一步精簡非核心代碼,增加可視化圖表以及文字的結論性分析。

    博客定位:基于 Android 6.0的源碼 ,專注于分享Android系統原理、架構分析的原創文章。 建議閱讀群體 : 適合于正從事或者有興趣研究Android系統的工程師或者愛好者,也適合Android app高級工程師; 對于尚未入門或者剛入門的app程序員閱讀可能會困難些,可能不是很適合。

    4.0 學習篇

    看到Android整個系統架構是如此龐大的, 該問如何學習Android系統, 以下是我自己琢磨的Android的學習和研究論,僅供參考:

    4.1 進程篇

    進程對于系統非常之重要,系統運轉,各種服務、組件的載體都依托于進程,對進程理解越深刻,越能掌握系統整體架構。那么先來看看進程相關:

    4.2 系統啟動篇

    Android系統啟動-概述): Android系統啟動過程中,有幾個非常重要的進程: init 、 Zygote 、 system_server 進程:

 本文由用戶 alleyway 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!