Android系统架构开篇
Android系統(tǒng)龐大且錯綜復雜,Gityuan帶領大家初探Android系統(tǒng)整體架構,一窺其全貌。
一、引言
本文作為Android系統(tǒng)架構的開篇,起到提綱挈領的作用,從系統(tǒng)整體架構角度概要講解Android系統(tǒng)的核心技術點,帶領大家初探Android系統(tǒng)全貌以及內(nèi)部運作機制。雖然Android系統(tǒng)非常龐大且錯綜復雜,需要具備全面的技術棧,但整體架構設計清晰。Android底層內(nèi)核空間以Linux Kernel作為基石,上層用戶空間由Native系統(tǒng)庫、虛擬機運行環(huán)境、框架層組成,通過系統(tǒng)調(diào)用(Syscall)連通系統(tǒng)的內(nèi)核空間與用戶空間。對于用戶空間主要采用C++和Java代碼編寫,通過JNI技術打通用戶空間的Java層和Native層(C++/C),從而連通整個系統(tǒng)。
為了能讓大家整體上大致了解Android系統(tǒng)涉及的知識層面,先來看一張Google官方提供的經(jīng)典分層架構圖,從下往上依次分為Linux內(nèi)核、HAL、系統(tǒng)Native庫和Android運行時環(huán)境、Java框架層以及應用層這5層架構,其中每一層都包含大量的子模塊或子系統(tǒng)。
上圖采用靜態(tài)分層方式的架構劃分,眾所周知,程序代碼是死的,系統(tǒng)運轉(zhuǎn)是活的,各模塊代碼運行在不同的進程(線程)中,相互之間進行著各種錯終復雜的信息傳遞與交互流,從這個角度來說此圖并沒能體現(xiàn)Android整個系統(tǒng)的內(nèi)部架構、運行機理,以及各個模塊之間是如何銜接與配合工作的。為了更深入地掌握Android整個架構思想以及各個模塊在Android系統(tǒng)所處的地位與價值,計劃以Android系統(tǒng)啟動過程為主線,以進程的視角來詮釋Android M系統(tǒng)全貌,全方位的深度剖析各個模塊功能,爭取各個擊破。這樣才能猶如庖丁解牛,解決、分析問題則能游刃有余。
二、Android架構
Google提供的5層架構圖很經(jīng)典,但為了更進一步透視Android系統(tǒng)架構,本文更多的是以進程的視角,以分層的架構來詮釋Android系統(tǒng)的全貌,闡述Android內(nèi)部的環(huán)環(huán)相扣的內(nèi)在聯(lián)系。
系統(tǒng)啟動架構圖
圖解:Android系統(tǒng)啟動過程由上圖從下往上的一個過程是由Boot Loader引導開機,然后依次進入 -> Kernel -> Native -> Framework -> App,接來下簡要說說每個過程:
關于Loader層:
Boot ROM: 當手機處于關機狀態(tài)時,長按Power鍵開機,引導芯片開始從固化在?ROM里的預設代碼開始執(zhí)行,然后加載引導程序到?RAM;
Boot Loader:這是啟動Android系統(tǒng)之前的引導程序,主要是檢查RAM,初始化硬件參數(shù)等功能。
2.1 Linux內(nèi)核層
Android平臺的基礎是Linux內(nèi)核,比如ART虛擬機最終調(diào)用底層Linux內(nèi)核來執(zhí)行功能。Linux內(nèi)核的安全機制為Android提供相應的保障,也允許設備制造商為內(nèi)核開發(fā)硬件驅(qū)動程序。
啟動Kernel的swapper進程(pid=0):該進程又稱為idle進程, 系統(tǒng)初始化過程Kernel由無到有開創(chuàng)的第一個進程, 用于初始化進程管理、內(nèi)存管理,加載Display,Camera Driver,Binder Driver等相關工作;
啟動kthreadd進程(pid=2):是Linux系統(tǒng)的內(nèi)核進程,會創(chuàng)建內(nèi)核工作線程kworkder,軟中斷線程ksoftirqd,thermal等內(nèi)核守護進程。?kthreadd進程是所有內(nèi)核進程的鼻祖。
2.2 硬件抽象層 (HAL)
硬件抽象層 (HAL) 提供標準接口,HAL包含多個庫模塊,其中每個模塊都為特定類型的硬件組件實現(xiàn)一組接口,比如WIFI/藍牙模塊,當框架API請求訪問設備硬件時,Android系統(tǒng)將為該硬件加載相應的庫模塊。
2.3 Android Runtime & 系統(tǒng)庫
每個應用都在其自己的進程中運行,都有自己的虛擬機實例。ART通過執(zhí)行DEX文件可在設備運行多個虛擬機,DEX文件是一種專為Android設計的字節(jié)碼格式文件,經(jīng)過優(yōu)化,使用內(nèi)存很少。ART主要功能包括:預先(AOT)和即時(JIT)編譯,優(yōu)化的垃圾回收(GC),以及調(diào)試相關的支持。
這里的Native系統(tǒng)庫主要包括init孵化來的用戶空間的守護進程、HAL層以及開機動畫等。啟動init進程(pid=1),是Linux系統(tǒng)的用戶進程, init進程是所有用戶進程的鼻祖。
init進程會孵化出ueventd、logd、healthd、installd、adbd、lmkd等用戶守護進程;
init進程還啟動?servicemanager(binder服務管家)、?bootanim(開機動畫)等重要服務
init進程孵化出Zygote進程,Zygote進程是Android系統(tǒng)的第一個Java進程(即虛擬機進程),?Zygote是所有Java進程的父進程,Zygote進程本身是由init進程孵化而來的。
2.4 Framework層
Zygote進程,是由init進程通過解析init.rc文件后fork生成的,Zygote進程主要包含:
加載ZygoteInit類,注冊Zygote Socket服務端套接字
加載虛擬機
提前加載類preloadClasses
提前加載資源preloadResouces
System Server進程,是由Zygote進程fork而來,?SystemServer是Zygote孵化的第一個進程,System Server負責啟動和管理整個Java framework,包含ActivityManager,WindowManager,PackageManager,PowerManager等服務。
Media Server進程,是由init進程fork而來,負責啟動和管理整個C++ framework,包含AudioFlinger,Camera Service等服務。
2.5 App層
Zygote進程孵化出的第一個App進程是Launcher,這是用戶看到的桌面App;
Zygote進程還會創(chuàng)建Browser,Phone,Email等App進程,每個App至少運行在一個進程上。
所有的App進程都是由Zygote進程fork生成的。
2.6 Syscall && JNI
Native與Kernel之間有一層系統(tǒng)調(diào)用(SysCall)層,見Linux系統(tǒng)調(diào)用(Syscall)原理;
Java層與Native(C/C++)層之間的紐帶JNI,見Android JNI原理分析。
三、通信方式
無論是Android系統(tǒng),還是各種Linux衍生系統(tǒng),各個組件、模塊往往運行在各種不同的進程和線程內(nèi),這里就必然涉及進程/線程之間的通信。對于IPC(Inter-Process Communication, 進程間通信),Linux現(xiàn)有管道、消息隊列、共享內(nèi)存、套接字、信號量、信號這些IPC機制,Android額外還有Binder IPC機制,Android OS中的Zygote進程的IPC采用的是Socket機制,在上層system server、media server以及上層App之間更多的是采用Binder IPC方式來完成跨進程間的通信。對于Android上層架構中,很多時候是在同一個進程的線程之間需要相互通信,例如同一個進程的主線程與工作線程之間的通信,往往采用的Handler消息機制。
想深入理解Android內(nèi)核層架構,必須先深入理解Linux現(xiàn)有的IPC機制;對于Android上層架構,則最常用的通信方式是Binder、Socket、Handler,當然也有少量其他的IPC方式,比如殺進程Process.killProcess()采用的是signal方式。下面說說Binder、Socket、Handler:
3.1 Binder
Binder作為Android系統(tǒng)提供的一種IPC機制,無論從系統(tǒng)開發(fā)還是應用開發(fā),都是Android系統(tǒng)中最重要的組成,也是最難理解的一塊知識點,想了解為什么Android要采用Binder作為IPC機制? 可查看我在知乎上的回答。深入了解Binder機制,最好的方法便是閱讀源碼,借用Linux鼻祖Linus Torvalds曾說過的一句話:Read The Fucking Source Code。下面簡要說說Binder IPC原理。
Binder IPC原理
Binder通信采用c/s架構,從組件視角來說,包含Client、Server、ServiceManager以及binder驅(qū)動,其中ServiceManager用于管理系統(tǒng)中的各種服務。
想進一步了解Binder,可查看Binder系列—開篇,Binder系列花費了13篇文章的篇幅,從源碼角度出發(fā)來講述Driver、Native、Framework、App四個層面的整個完整流程。根據(jù)有些讀者反饋這個系列還是不好理解,這個binder涉及的層次跨度比較大,知識量比較廣,建議大家先知道binder是用于進程間通信,有個大致概念就可以先去學習系統(tǒng)基本知識,等后面有一定功力再進一步深入研究Binder機制。
Binder原理篇
| 0 | Binder系列—開篇 | Binder概述 |
| 1 | Binder系列3—啟動Service Manager | ServiceManager守護進程 注冊和查詢服務 |
| 2 | Binder系列4—獲取Service Manager | 獲取代理對象BpServiceManager |
| 3 | Binder系列5—注冊服務(addService) | 注冊Media服務 |
| 4 | Binder系列6—獲取服務(getService) | 獲取Media代理,以及DeathRecipient |
| 5 | Binder系列7—framework層分析 | framework層服務注冊和查詢,Binder注冊 |
| 6 | 理解Binder線程池的管理 | Binder的startThreadPool過程 |
| 7 | 徹底理解Android Binder通信架構 | startService為主線 |
| 8 | Binder系列10—總結 | Binder的簡單總結 |
| 9 | Binder IPC的權限控制 | clearCallingIdentity/restoreCallingIdentity |
| 10 | Binder死亡通知機制之linkToDeath | Binder死亡通知機制 |
Binder驅(qū)動篇:
| 1 | Binder Driver初探 | 驅(qū)動open/mmap/ioctl,以及binder結構體 |
| 2 | Binder Driver再探 | Binder通信協(xié)議,內(nèi)存機制 |
Binder使用篇:
| 1 | 如何使用Binder | Native層、Framwrok層自定義Binder服務 |
| 2 | 如何使用AIDL | App層自定義Binder服務 |
3.2 Socket
Socket通信方式也是C/S架構,比Binder簡單很多。在Android系統(tǒng)中采用Socket通信方式的主要有:
zygote:用于孵化進程,system_server創(chuàng)建進程是通過socket向zygote進程發(fā)起請求;
installd:用于安裝App的守護進程,上層PackageManagerService很多實現(xiàn)最終都是交給它來完成;
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用于進程間通信,能否用于線程間通信呢?答案是肯定,對于兩個具有獨立地址空間的進程通信都可以,當然也能用于共享內(nèi)存空間的兩個線程間通信,這就好比殺雞用牛刀。接著可能還有人會疑惑,那handler消息機制能否用于進程間通信?答案是不能,Handler只能用于共享內(nèi)存地址空間的兩個線程間通信,即同進程的兩個線程間通信。很多時候,Handler是工作線程向UI主線程發(fā)送消息,即App應用中只有主線程能更新UI,其他工作線程往往是完成相應工作后,通過Handler告知主線程需要做出相應地UI更新操作,Handler分發(fā)相應的消息給UI主線程去完成,如下圖:
由于工作線程與主線程共享地址空間,即Handler實例對象mHandler位于線程間共享的內(nèi)存堆上,工作線程與主線程都能直接使用該對象,只需要注意多線程的同步問題。工作線程通過mHandler向其成員變量MessageQueue中添加新Message,主線程一直處于loop()方法內(nèi),當收到新的Message時按照一定規(guī)則分發(fā)給相應的handleMessage()方法來處理。所以說,Handler消息機制用于同進程的線程間通信,其核心是線程間共享內(nèi)存空間,而不同進程擁有不同的地址空間,也就不能用handler來實現(xiàn)進程間通信。
上圖只是Handler消息機制的一種處理流程,是不是只能工作線程向UI主線程發(fā)消息呢,其實不然,可以是UI線程向工作線程發(fā)送消息,也可以是多個工作線程之間通過handler發(fā)送消息。更多關于Handler消息機制文章:
Android消息機制-Handler(framework篇)
Android消息機制-Handler(native篇)
Android消息機制3-Handler(實戰(zhàn))
要理解framework層源碼,掌握這3種基本的進程/線程間通信方式是非常有必要,當然Linux還有不少其他的IPC機制,比如共享內(nèi)存、信號、信號量,在源碼中也有體現(xiàn),如果想全面徹底地掌握Android系統(tǒng),還是需要對每一種IPC機制都有所了解。
四、核心提綱
博主對于Android從系統(tǒng)底層一路到上層都有自己的理解和沉淀,通過前面對系統(tǒng)啟動的介紹,相信大家對Android系統(tǒng)有了一個整體觀。接下來需抓核心、理思路,爭取各個擊破。后續(xù)將持續(xù)更新和完善整個大綱,不限于進程、內(nèi)存、IO、系統(tǒng)服務架構以及分析實戰(zhàn)等文章。
當然本站有一些文章沒來得及進一步加工,有時間根據(jù)大家的反饋,不斷修正和完善所有文章,爭取給文章,再進一步精簡非核心代碼,增加可視化圖表以及文字的結論性分析。基于Android 6.0的源碼,專注于分享Android系統(tǒng)原理、架構分析的原創(chuàng)文章。
建議閱讀群體: 適合于正從事或者有興趣研究Android系統(tǒng)的工程師或者技術愛好者,也適合Android App高級工程師;對于尚未入門或者剛?cè)腴T的App工程師閱讀可能會有點困難,建議先閱讀更基礎的資料,再來閱讀本站博客。
看到Android整個系統(tǒng)架構是如此龐大的, 該問如何學習Android系統(tǒng), 以下是我自己的Android的學習和研究論,僅供參考如何自學Android。
從整理上來列舉一下Android系統(tǒng)的核心知識點概覽:
4.1 系統(tǒng)啟動系列
Android系統(tǒng)啟動-概述:
Android系統(tǒng)中極其重要進程:init, zygote, system_server, servicemanager 進程:
| 1 | init進程 | Linux系統(tǒng)中用戶空間的第一個進程, Init.main |
| 2 | zygote進程 | 所有App進程的父進程, ZygoteInit.main |
| 3 | system_server進程(上篇) | 系統(tǒng)各大服務的載體, forkSystemServer過程 |
| 4 | system_server進程(下篇) | 系統(tǒng)各大服務的載體, SystemServer.main |
| 5 | servicemanager進程 | binder服務的大管家, 守護進程循環(huán)運行在binder_loop |
| 6 | App進程 | 通過Process.start啟動App進程, ActivityThread.main |
再來看看守護進程(也就是進程名一般以d為后綴,比如logd,此處d是指daemon的簡稱), 下面介紹部分守護進程:
debuggerd
installd
lmkd
logd
4.2 系統(tǒng)穩(wěn)定性系列
Android系統(tǒng)穩(wěn)定性主要是異常崩潰(crash)和執(zhí)行超時(timeout),:
| 1 | 理解Android ANR的觸發(fā)原理 | 觸發(fā)ANR的場景以及機理 |
| 2 | Input系統(tǒng)—ANR原理分析 | input觸發(fā)ANR的原理 |
| 3 | 理解Android ANR的信息收集過程 | AMS.appNotResponding過程分析,收集traces |
| 4 | 解讀Java進程的Trace文件 | kill -3 信息收集過程 |
| 5 | Native進程之Trace原理 | debuggerd -b 信息收集過程 |
| 6 | WatchDog工作原理 | WatchDog觸發(fā)機制 |
| 7 | 理解Java Crash處理流程 | AMS.handleApplicationCrash過程分析 |
| 8 | 理解Native Crash處理流程 | debuggerd守護進程 |
| 9 | global reference限制策略 | global reference |
4.3 Android進程系列
進程/線程是操作系統(tǒng)的魂,各種服務、組件、子系統(tǒng)都是依附于具體的進程實體。深入理解進程機制對于掌握Android系統(tǒng)整體架構和運轉(zhuǎn)機制是非常有必要的,是系統(tǒng)工程師的基本功,下面列舉進程相關的文章:
| 1 | 理解Android進程創(chuàng)建流程 | Process.start過程分析 |
| 2 | 理解殺進程的實現(xiàn)原理 | Process.killProcess過程分析 |
| 3 | Android四大組件與進程啟動的關系 | AMS.startProcessLocked過程分析組件與進程 |
| 4 | Android進程絕殺技--forceStop | force-stop過程分析徹底移除組件與殺進程 |
| 5 | 理解Android線程創(chuàng)建流程 | 3種不同線程的創(chuàng)建過程 |
| 6 | 徹底理解Android Binder通信架構 | 以start-service為線,闡述進程間通信機理 |
| 7 | 理解Binder線程池的管理 | Zygote fork的進程都默認開啟binder線程池 |
| 8 | Android進程生命周期與ADJ | 進程adj, processState以及l(fā)mk |
| 9 | Android LowMemoryKiller原理分析 | lmk原理分析 |
| 10 | 進程優(yōu)先級 | 進程nice,thread priority以及scheduler |
| 11 | Android進程調(diào)度之a(chǎn)dj算法 | updateOomAdjLocked過程 |
| 12 | Android進程整理 | 整理系統(tǒng)的所有進程/線程 |
4.4 四大組件系列
對于App來說,Android應用的四大組件Activity,Service,Broadcast Receiver, Content Provider最為核心,接下分別展開介紹:
| 1 | startActivity啟動過程分析 | Activity |
| 2 | 簡述Activity生命周期 | Activity |
| 3 | startService啟動過程分析 | Service |
| 4 | bindService啟動過程分析 | Service |
| 5 | 以Binder視角來看Service啟動 | Service |
| 6 | Android Broadcast廣播機制分析 | Broadcast |
| 7 | 理解ContentProvider原理 | ContentProvider |
| 8 | ContentProvider引用計數(shù) | ContentProvider |
| 9 | Activity與Service生命周期 | Activity&&Service |
| 10 | 簡述Activity與Window關系 | Activity&&Window |
| 11 | 四大組件之綜述 | AMS |
| 12 | 四大組件之ServiceRecord | Service |
| 13 | 四大組件之BroadcastRecord | Broadcast |
| 14 | 四大組件之ContentProviderRecord | ContentProvider |
| 15 | 理解Android Context | Context |
| 16 | 理解Application創(chuàng)建過程 | Application |
| 17 | unbindService流程分析 | Service |
| 18 | 四大組件之ActivityRecord | Activity |
| 19 | AMS總結(一) | AMS |
4.5 圖形系統(tǒng)系列
圖形也是整個系統(tǒng)非常復雜且重要的一個系列,涉及WindowManager,SurfaceFlinger服務。
| 1 | WindowManager啟動篇 | Window |
| 2 | WMS之啟動窗口篇 | Window |
| 3 | 以Window視角來看startActivity | Window |
| 4 | Android圖形系統(tǒng)概述 | SurfaceFlinger |
| 5 | SurfaceFlinger啟動篇 | SurfaceFlinger |
| 6 | SurfaceFlinger繪圖篇 | SurfaceFlinger |
| 7 | Choreographer原理 | Choreographer |
4.6 系統(tǒng)服務篇
再則就是在整個架構中有大量的服務,都是基于Binder來交互的,Android系統(tǒng)服務的注冊過程也是在此之上的構建的。計劃針對部分核心服務來重點分析:
AMS服務
AMS啟動過程(一)
更多組件篇[見小節(jié)4.3]
Input系統(tǒng)
Input系統(tǒng)—啟動篇
Input系統(tǒng)—InputReader線程
Input系統(tǒng)—InputDispatcher線程
Input系統(tǒng)—UI線程
Input系統(tǒng)—進程交互
Input系統(tǒng)—ANR原理分析
PKMS服務
PackageManager啟動篇
Installd守護進程
Alarm服務
理解AlarmManager機制
JobScheduler服務
理解JobScheduler機制
BatteryService
Android耗電統(tǒng)計算法
PMS服務
DropBox服務
DropBoxManager啟動篇
UserManagerService
多用戶管理UserManager
更多系統(tǒng)服務
敬請期待
4.7 內(nèi)存&&存儲篇
內(nèi)存篇
Android LowMemoryKiller原理分析
Linux內(nèi)存管理
Android內(nèi)存分析命令
存儲篇
Android存儲系統(tǒng)之源碼篇
Android存儲系統(tǒng)之架構篇
Linux驅(qū)動篇
敬請期待
dalvik/art
解讀Java進程的Trace文件
4.8 工具篇
再來說說Android相關的一些常用命令和工具以及調(diào)試手段.
| 1 | 理解Android編譯命令 | build |
| 2 | 理解Android.bp | build |
| 2 | 性能工具Systrace | systrace |
| 3 | Android內(nèi)存分析命令 | Memory |
| 4 | ps進程命令 | Process |
| 5 | Am命令用法 | Am |
| 6 | Pm命令用法 | Pm |
| 7 | 調(diào)試系列1:bugreport源碼篇 | bugreport |
| 8 | 調(diào)試系列2:bugreport實戰(zhàn)篇 | bugreport |
| 9 | dumpsys命令用法 | dumpsys |
| 10 | Android logd日志原理 | logd |
| 11 | 介紹gdb調(diào)試工具 | gdb |
| 12 | 介紹addr2line調(diào)試命令 | addr2line |
4.9 實戰(zhàn)篇
下面列舉處理過的部分較為典型的案例,供大家參考
| 1 | Binder Driver缺陷導致定屏的案例 | binder |
| 2 | 深度解讀ArrayMap優(yōu)勢與缺陷 | ArrayMap |
| 3 | 數(shù)組越界導致系統(tǒng)重啟的案例 | 數(shù)組越界 |
| 4 | 一行Log引發(fā)多線程并發(fā)問題的案例 | 多線程并發(fā) |
| 5 | 跑monkey壓力測試過程的凍屏案例 | monkey凍屏 |
| 6 | 深度剖析APP保活案例 | 保活 |
本文只是提綱挈領的篇章,更多詳細文章可點擊下方閱讀原文,進入我的博客Gityuan.com閱讀,博主仍在持續(xù)更新。
五、結束語
Android系統(tǒng)之博大精深,包括Linux內(nèi)核、Native、虛擬機、Framework,通過系統(tǒng)調(diào)用連通內(nèi)核與用戶空間,通過JNI打通用戶空間的Java層和Native層,通過Binder、Socket、Handler等打通跨進程、跨線程的信息交換。只有真正閱讀并理解系統(tǒng)核心架構的設計,解決問題和設計方案才能做到心中無劍勝有劍,才能做到知其然知其所以然。當修煉到此,恭喜你對系統(tǒng)有了更高一個層次的理解,正如太極劍法,忘記了所有招式,也就練成了太極劍法。
再回過頭去看看那些API,看到的將不再是一行行代碼、一個個接口的調(diào)用,而是各種信息的傳遞與交互工作,而是背后成千上萬個小蝌蚪的動態(tài)執(zhí)行流。記得《俠客行》里面的龍木二島主終其一生也無法參透太玄經(jīng),石破天卻短短數(shù)日練成絕世神功,究其根源是龍木二島主以靜態(tài)視角去解讀太玄經(jīng),而石破天把墻壁的圖案想象成無數(shù)游動的蝌蚪,最終成就絕世神功。一言以蔽之,程序代碼是死的,系統(tǒng)運轉(zhuǎn)是活的,要以動態(tài)視角去理解系統(tǒng)架構。
推薦閱讀:
Android技術架構演進與未來
深度解讀ArrayMap優(yōu)勢與缺陷
解讀Android進程優(yōu)先級ADJ算法
Binder Driver缺陷導致定屏的實戰(zhàn)分析
覺得不錯
請點在看
↓
總結
以上是生活随笔為你收集整理的Android系统架构开篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springBoot集成Activiti
- 下一篇: 大神们都应该去哪里工作?