Android系統龐大且錯綜複雜,Gityuan帶領你們初探Android系統總體架構,一窺其全貌。算法
本文做爲Android系統架構的開篇,起到提綱挈領的做用,從系統總體架構角度概要講解Android系統的核心技術點,帶領你們初探Android系統全貌以及內部運做機制。雖然Android系統很是龐大且錯綜複雜,須要具有全面的技術棧,但總體架構設計清晰。Android底層內核空間以Linux Kernel做爲基石,上層用戶空間由Native系統庫、虛擬機運行環境、框架層組成,經過系統調用(Syscall)連通系統的內核空間與用戶空間。對於用戶空間主要採用C++和Java代碼編寫,經過JNI技術打通用戶空間的Java層和Native層(C++/C),從而連通整個系統。數組
爲了能讓你們總體上大體瞭解Android系統涉及的知識層面,先來看一張Google官方提供的經典分層架構圖,從下往上依次分爲Linux內核、HAL、系統Native庫和Android運行時環境、Java框架層以及應用層這5層架構,其中每一層都包含大量的子模塊或子系統。安全
上圖採用靜態分層方式的架構劃分,衆所周知,程序代碼是死的,系統運轉是活的,各模塊代碼運行在不一樣的進程(線程)中,相互之間進行着各類錯終複雜的信息傳遞與交互流,從這個角度來講此圖並沒能體現Android整個系統的內部架構、運行機理,以及各個模塊之間是如何銜接與配合工做的。爲了更深刻地掌握Android整個架構思想以及各個模塊在Android系統所處的地位與價值,計劃以Android系統啓動過程爲主線,以進程的視角來詮釋Android M系統全貌,全方位的深度剖析各個模塊功能,爭取各個擊破。這樣才能猶如庖丁解牛,解決、分析問題則能遊刃有餘。多線程
Google提供的5層架構圖很經典,但爲了更進一步透視Android系統架構,本文更多的是以進程的視角,以分層的架構來詮釋Android系統的全貌,闡述Android內部的環環相扣的內在聯繫。架構
系統啓動架構圖併發
圖解:Android系統啓動過程由上圖從下往上的一個過程是由Boot Loader引導開機,而後依次進入 -> Kernel -> Native -> Framework -> App,接來下簡要說說每一個過程:app
關於Loader層:框架
Boot ROM: 當手機處於關機狀態時,長按Power鍵開機,引導芯片開始從固化在 ROM裏的預設代碼開始執行,而後加載引導程序到 RAM;socket
Boot Loader:這是啓動Android系統以前的引導程序,主要是檢查RAM,初始化硬件參數等功能。ide
Android平臺的基礎是Linux內核,好比ART虛擬機最終調用底層Linux內核來執行功能。Linux內核的安全機制爲Android提供相應的保障,也容許設備製造商爲內核開發硬件驅動程序。
啓動Kernel的swapper進程(pid=0):該進程又稱爲idle進程, 系統初始化過程Kernel由無到有開創的第一個進程, 用於初始化進程管理、內存管理,加載Display,Camera Driver,Binder Driver等相關工做;
啓動kthreadd進程(pid=2):是Linux系統的內核進程,會建立內核工做線程kworkder,軟中斷線程ksoftirqd,thermal等內核守護進程。 kthreadd進程是全部內核進程的鼻祖。
硬件抽象層 (HAL) 提供標準接口,HAL包含多個庫模塊,其中每一個模塊都爲特定類型的硬件組件實現一組接口,好比WIFI/藍牙模塊,當框架API請求訪問設備硬件時,Android系統將爲該硬件加載相應的庫模塊。
每一個應用都在其本身的進程中運行,都有本身的虛擬機實例。ART經過執行DEX文件可在設備運行多個虛擬機,DEX文件是一種專爲Android設計的字節碼格式文件,通過優化,使用內存不多。ART主要功能包括:預先(AOT)和即時(JIT)編譯,優化的垃圾回收(GC),以及調試相關的支持。
這裏的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進程孵化而來的。
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等服務。
Zygote進程孵化出的第一個App進程是Launcher,這是用戶看到的桌面App;
Zygote進程還會建立Browser,Phone,Email等App進程,每一個App至少運行在一個進程上。
全部的App進程都是由Zygote進程fork生成的。
Native與Kernel之間有一層系統調用(SysCall)層,見Linux系統調用(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:
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機制。
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驅動篇:
1 | Binder Driver初探 | 驅動open/mmap/ioctl,以及binder結構體 |
2 | Binder Driver再探 | Binder通訊協議,內存機制 |
Binder使用篇:
1 | 如何使用Binder | Native層、Framwrok層自定義Binder服務 |
2 | 如何使用AIDL | App層自定義Binder服務 |
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比較簡單,這裏省略。
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消息機制文章:
Android消息機制-Handler(framework篇)
Android消息機制-Handler(native篇)
Android消息機制3-Handler(實戰)
要理解framework層源碼,掌握這3種基本的進程/線程間通訊方式是很是有必要,固然Linux還有很多其餘的IPC機制,好比共享內存、信號、信號量,在源碼中也有體現,若是想全面完全地掌握Android系統,仍是須要對每一種IPC機制都有所瞭解。
博主對於Android從系統底層一路到上層都有本身的理解和沉澱,經過前面對系統啓動的介紹,相信你們對Android系統有了一個總體觀。接下來需抓核心、理思路,爭取各個擊破。後續將持續更新和完善整個大綱,不限於進程、內存、IO、系統服務架構以及分析實戰等文章。
固然本站有一些文章沒來得及進一步加工,有時間根據你們的反饋,不斷修正和完善全部文章,爭取給文章,再進一步精簡非核心代碼,增長可視化圖表以及文字的結論性分析。基於Android 6.0的源碼,專一於分享Android系統原理、架構分析的原創文章。
建議閱讀羣體: 適合於正從事或者有興趣研究Android系統的工程師或者技術愛好者,也適合Android App高級工程師;對於還沒有入門或者剛入門的App工程師閱讀可能會有點困難,建議先閱讀更基礎的資料,再來閱讀本站博客。
看到Android整個系統架構是如此龐大的, 該問如何學習Android系統, 如下是我本身的Android的學習和研究論,僅供參考如何自學Android。
從整理上來列舉一下Android系統的核心知識點概覽:
4.1 系統啓動系列
Android系統啓動-概述:
Android系統中極其重要進程:init, zygote, system_server, servicemanager 進程:
序號 | 進程啓動 | 概述 |
---|---|---|
1 | init進程 | Linux系統中用戶空間的第一個進程, Init.main |
2 | zygote進程 | 全部App進程的父進程, ZygoteInit.main |
3 | system_server進程(上篇) | 系統各大服務的載體, forkSystemServer過程 |
4 | system_server進程(下篇) | 系統各大服務的載體, SystemServer.main |
5 | servicemanager進程 | binder服務的大管家, 守護進程循環運行在binder_loop |
6 | App進程 | 經過Process.start啓動App進程, ActivityThread.main |
再來看看守護進程(也就是進程名通常以d爲後綴,好比logd,此處d是指daemon的簡稱), 下面介紹部分守護進程:
debuggerd
installd
lmkd
logd
Android系統穩定性主要是異常崩潰(crash)和執行超時(timeout),:
序號 | 文章名 | 概述 |
---|---|---|
1 | 理解Android ANR的觸發原理 | 觸發ANR的場景以及機理 |
2 | Input系統—ANR原理分析 | input觸發ANR的原理 |
3 | 理解Android ANR的信息收集過程 | AMS.appNotResponding過程分析,收集traces |
4 | 解讀Java進程的Trace文件 | kill -3 信息收集過程 |
5 | Native進程之Trace原理 | debuggerd -b 信息收集過程 |
6 | WatchDog工做原理 | WatchDog觸發機制 |
7 | 理解Java Crash處理流程 | AMS.handleApplicationCrash過程分析 |
8 | 理解Native Crash處理流程 | debuggerd守護進程 |
9 | global reference限制策略 | global reference |
進程/線程是操做系統的魂,各類服務、組件、子系統都是依附於具體的進程實體。深刻理解進程機制對於掌握Android系統總體架構和運起色制是很是有必要的,是系統工程師的基本功,下面列舉進程相關的文章:
序號 | 文章名 | 概述 |
---|---|---|
1 | 理解Android進程建立流程 | Process.start過程分析 |
2 | 理解殺進程的實現原理 | Process.killProcess過程分析 |
3 | Android四大組件與進程啓動的關係 | AMS.startProcessLocked過程分析組件與進程 |
4 | Android進程絕殺技--forceStop | force-stop過程分析完全移除組件與殺進程 |
5 | 理解Android線程建立流程 | 3種不一樣線程的建立過程 |
6 | 完全理解Android Binder通訊架構 | 以start-service爲線,闡述進程間通訊機理 |
7 | 理解Binder線程池的管理 | Zygote fork的進程都默認開啓binder線程池 |
8 | Android進程生命週期與ADJ | 進程adj, processState以及lmk |
9 | Android LowMemoryKiller原理分析 | lmk原理分析 |
10 | 進程優先級 | 進程nice,thread priority以及scheduler |
11 | Android進程調度之adj算法 | updateOomAdjLocked過程 |
12 | Android進程整理 | 整理系統的全部進程/線程 |
對於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引用計數 | 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建立過程 | Application |
17 | unbindService流程分析 | Service |
18 | 四大組件之ActivityRecord | Activity |
19 | AMS總結(一) | AMS |
圖形也是整個系統很是複雜且重要的一個系列,涉及WindowManager,SurfaceFlinger服務。
序號 | 文章名 | 類別 |
---|---|---|
1 | WindowManager啓動篇 | Window |
2 | WMS之啓動窗口篇 | Window |
3 | 以Window視角來看startActivity | Window |
4 | Android圖形系統概述 | SurfaceFlinger |
5 | SurfaceFlinger啓動篇 | SurfaceFlinger |
6 | SurfaceFlinger繪圖篇 | SurfaceFlinger |
7 | Choreographer原理 | Choreographer |
再則就是在整個架構中有大量的服務,都是基於Binder來交互的,Android系統服務的註冊過程也是在此之上的構建的。計劃針對部分核心服務來重點分析:
AMS服務
AMS啓動過程(一)
更多組件篇[見小節4.3]
Input系統
Input系統—啓動篇
Input系統—InputReader線程
Input系統—InputDispatcher線程
Input系統—UI線程
Input系統—進程交互
Input系統—ANR原理分析
PKMS服務
PackageManager啓動篇
Installd守護進程
Alarm服務
理解AlarmManager機制
JobScheduler服務
理解JobScheduler機制
BatteryService
Android耗電統計算法
PMS服務
DropBox服務
DropBoxManager啓動篇
UserManagerService
多用戶管理UserManager
更多系統服務
敬請期待
內存篇
Android LowMemoryKiller原理分析
Linux內存管理
Android內存分析命令
存儲篇
Android存儲系統之源碼篇
Android存儲系統之架構篇
Linux驅動篇
敬請期待
dalvik/art
解讀Java進程的Trace文件
再來講說Android相關的一些經常使用命令和工具以及調試手段.
序號 | 文章名 | 類別 |
---|---|---|
1 | 理解Android編譯命令 | build |
2 | 理解Android.bp | build |
2 | 性能工具Systrace | systrace |
3 | Android內存分析命令 | Memory |
4 | ps進程命令 | Process |
5 | Am命令用法 | Am |
6 | Pm命令用法 | Pm |
7 | 調試系列1:bugreport源碼篇 | bugreport |
8 | 調試系列2:bugreport實戰篇 | bugreport |
9 | dumpsys命令用法 | dumpsys |
10 | Android logd日誌原理 | logd |
11 | 介紹gdb調試工具 | gdb |
12 | 介紹addr2line調試命令 | addr2line |
下面列舉處理過的部分較爲典型的案例,供你們參考
序號 | 文章名 | 類別 |
---|---|---|
1 | Binder Driver缺陷致使定屏的案例 | binder |
2 | 深度解讀ArrayMap優點與缺陷 | ArrayMap |
3 | 數組越界致使系統重啓的案例 | 數組越界 |
4 | 一行Log引起多線程併發問題的案例 | 多線程併發 |
5 | 跑monkey壓力測試過程的凍屏案例 | monkey凍屏 |
6 | 深度剖析APP保活案例 | 保活 |
本文只是提綱挈領的篇章,更多詳細文章可點擊下方閱讀原文,進入個人博客Gityuan.com閱讀,博主仍在持續更新。
Android系統之博大精深,包括Linux內核、Native、虛擬機、Framework,經過系統調用連通內核與用戶空間,經過JNI打通用戶空間的Java層和Native層,經過Binder、Socket、Handler等打通跨進程、跨線程的信息交換。只有真正閱讀並理解系統核心架構的設計,解決問題和設計方案才能作到心中無劍勝有劍,才能作到知其然知其因此然。當修煉到此,恭喜你對系統有了更高一個層次的理解,正如太極劍法,忘記了全部招式,也就練成了太極劍法。
再回過頭去看看那些API,看到的將再也不是一行行代碼、一個個接口的調用,而是各類信息的傳遞與交互工做,而是背後成千上萬個小蝌蚪的動態執行流。記得《俠客行》裏面的龍木二島主終其一輩子也沒法參透太玄經,石破天卻短短很多天練成絕世神功,究其根源是龍木二島主以靜態視角去解讀太玄經,而石破天把牆壁的圖案想象成無數遊動的蝌蚪,最終成就絕世神功。一言以蔽之,程序代碼是死的,系統運轉是活的,要以動態視角去理解系統架構。