您好,登錄后才能下訂單哦!
目錄
Android系統架構ABC
1) Android的歷史
2) Android 系統框架一覽
a)應用程序層
b) 應用程序框架層
c)系統庫和Android運行時
Dalvik模式的缺點
ART模式(Android Runtime)的優點
d) Linux內核
Android 開源框架
Android 標準庫
3) 通信基石 – Binder模式
IPC機制種類
Binder通信機制簡介
為啥新發明一個Binider通信機制
Binder通信模型
Binder通信機制原理圖
J2EE和Android兩種RPC的比較:
4) 消息隊列(MessageQueue, Looper, Handler)
5) Framework啟動過程: zygote進程和system進程
6) 包管理服務PackageManagerService
7) 第一個應用程序進程的啟動過程
8) AMS活動管理, WMS窗口管理, View系統的工作原理
android內核三大核心成員介紹
整個Android生態系統工作原理概述
9) 總結
了解一個事物,往往要從其出身開始,這樣才能完整地明白它到底是什么東西。Android的歷史淵源要追溯到90年代初,Andriod之父 Andy Rubin還在蘋果子公司開發第一代手機OS “MagicCap”開始。
我用一段話簡短概述iPhone和Android,蘋果和谷歌之間的爭端的歷史緣由:
IOS產生的歷史:
Steve Jobs 于1976年創建了蘋果公司, 后于1985年離開蘋果,創立了“NeXTComputer”這家公司,創建了一款用Object-C語言編寫的叫“NeXTSTEP”的OS,之后在”NeXTSTEP”基礎上創造了“Mac OSX”系統,這就是iPhone OS 的基礎,簡稱IOS。后來1996年底,蘋果公司又收購NeXT公司,這樣Jobs又回到了蘋果公司。
Android產生的歷史:
1990年,蘋果公司的手持設備部門獨立,特地成立了”GeneralMagic” 的子公司,研究手機操作系統。”Android之父” ,89年剛進蘋果公司的26歲的年輕人——Andy Rubin,認定手機OS發展前景良好,也加入了這個部門, 參與了”MagicCap” OS的開發,后于95年離開了蘋果公司。2003年,Andy Rubin創建了Android公司,僅僅22個月之后,2005年被谷歌收購!然后,谷歌Android部門立馬投入展開了短信、手機檢索等業務,同時基于Linux的通用平臺也進入了開發。經過2年的研究,2007年11月5日, Android第一代系統 1.0 beta發布,不過只作為一個面向開發者的軟件開發包(SDK)進行發布。之后經過1年的不斷優化,于2008年9月23日,發布Android操作系統中的第一個正式版本:Android 1.0,代號為鐵臂阿童木(Astro)。僅僅1年之后,便開始了Android打敗諾基亞的Symbian,與IPhone兩分天下的輝煌時代!
總而言之,無論Android 還是 iPhone, 都是蘋果的員工辭職之后,搞出來的。這就是Android和iPhone與蘋果公司的淵源!!!這也是蘋果一直將安卓列為侵權產品的緣由。蘋果方面表示,Android系統創始人Andy Rubin有關Android系統的理念之一誕生于他供職蘋果期間。
具體iPhone和Android產生的歷史淵源可以查看鏈接:
http://tech.163.com/14/0426/11/9QOMTFMT00094ODU.html
具體Android各個歷史版本可以查看鏈接:
http://zh.wikipedia.org/zh-cn/Android%E6%AD%B7%E5%8F%B2%E7%89%88%E6%9C%AC
該層提供一些核心應用程序包,例如電子郵件、短信、日歷、地圖、瀏覽器和聯系人管理等。同時,開發者可以利用Java語言設計和編寫屬于自己的應用程序,而這些程序與那些核心應用程序彼此平等、友好共處。
該層是Android應用開發的基礎,開發人員大部分情況是在和她打交道。應用程序框架層包括活動管理器、窗口管理器、內容提供者、視圖系統、包管理器、電話管理器、資源管理器、位置管理器、通知管理器和XMPP服務十個部分。在Android平臺上,開發人員可以完全訪問核心應用程序所使用的API框架。并且,任何一個應用程序都可以發布自身的功能模塊,而其他應用程序則可以使用這些已發布的功能模塊。基于這樣的重用機制,用戶就可以方便地替換平臺本身的各種應用程序組件。
系統庫包括九個子系統,分別是圖層管理、媒體庫、SQLite、OpenGLEState、FreeType、WebKit、SGL、SSL和libc。Android運行時包括核心庫和Dalvik虛擬機,前者既兼容了大多數Java語言所需要調用的功能函數,又包括了Android的核心庫,比如android.os、android.net、android.media等等。后者是一種基于寄存器的java虛擬機,Dalvik虛擬機主要是完成對生命周期的管理、堆棧的管理、線程的管理、安全和異常的管理以及垃圾回收等重要功能。不過,最新的AndroidL 5.0 將徹底拋棄Dalvik虛擬機,改用ART模式。
在Dalvik虛擬機中,因此應用程序每次運行的時候,一部分代碼都需要重新進行編譯,這過程需要消耗一定的時間和降低應用的執行效率,最明顯的便是拖延了應用的啟動時間和降低運行速度。
通過在安裝應用程序時,自動對程序進行代碼預讀取編譯(可能比較耗時,占用更多ROM內存),讓程序直接編譯成機器語言,免去了Dalvik模式要時時轉換代碼,實現高效率、省電、占用更低的系統內存、手機運行流暢。
Android核心系統服務依賴于Linux2.6內核,如安全性、內存管理、進程管理、網絡協議棧和驅動模型。Linux內核也是作為硬件與軟件棧的抽象層。驅動:顯示驅動、攝像頭驅動、鍵盤驅動、WiFi驅動、Audio驅動、flash內存驅動、Binder(IPC)驅動、電源管理等。
在下面的圖中,綠色的大部分組件是基于Apache許可證開源,其余基于GPL、LGPL和BSD。
在Linux中,是以進程為單位分配和管理資源的。出于保護機制,一個進程不能直接訪問另一個進程的資源,也就是說,進程之間互相封閉
1-采用命名管道(named pipe)
2-消息隊列(message queue)
3- 信號(signal)
4-共享內存(share memory)
5 - Socket
在Android終端上的應用軟件的通信幾乎看不到這些IPC通信方式,取而代之的是Binder方式。
Binder使用Client-Server通信方式:一個進程作為Server提供諸如視頻/音頻解碼,視頻捕獲,地址本查詢,網絡連接等服務;多個進程作為Client向Server發起服務請求,獲得所需要的服務。要想實現Client-Server通信據必須實現以下兩點:
一,是server 必須有確定的訪問接入點或者說地址來接受Client的請求,并且Client可以通過某種途徑獲知Server的地址
二,是制定Command- Reply協議來傳輸數據。例如在網絡通信中Server的訪問接入點就是Server主機的IP地址+端口號,傳輸協議為TCP協議。對Binder而言,Binder可以看成Server提供的實現某個特定服務的訪問接入點, Client通過這個‘地址’向Server發送請求來使用該服務;對Client而言,Binder可以看成是通向Server的管道入口,要想和某個 Server通信首先必須建立這個管道并獲得管道入口
也可以在這些底層機制上架設一套協議來實現Client-Server通信,但這樣增加了系統的復雜性,在手機這種條件復雜,資源稀缺的環境下可靠性也難以保證。
socket作為一款通用接口,其傳輸效率低,開銷大,主要用在跨網絡的進程間通信和本機上進程間的低速通信。
消息隊列和管道采用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開辟的緩存區中,然后再從內核緩存區拷貝到接收方緩存區,至少有兩次拷貝過程。
共享內存雖然無需拷貝,但控制復雜,難以使用
數據拷貝次數比較圖:
IPC進程間通信類型 | 數據拷貝次數 |
共享內存 | 0 |
Binder | 1 |
Socket/管道/消息隊列 | 2 |
Android作為一個開放式,擁有眾多開發者的的平臺,應用程序的來源廣泛,確保智能終端的安全是非常重要的。終端用戶不希望從網上下載的程序在不知情的情況下偷窺隱私數據,連接無線網絡,長期操作底層設備導致電池很快耗盡等等。傳統IPC沒有任何安全措施,完全依賴上層協議來確保。
首先傳統IPC的接收方無法獲得對方進程可靠的UID/PID(用戶ID/進程ID),從而無法鑒別對方身份。Android為每個安裝好的應用程序分配了自己的UID,故進程的UID是鑒別進程身份的重要標志。使用傳統IPC只能由用戶在數據包里填入UID/PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標記只有由IPC機制本身在內核中添加。
其次傳統IPC訪問接入點是開放的,無法建立私有通道。比如命名管道的名稱,system V的鍵值,socket的ip地址或文件名都是開放的,只要知道這些接入點的程序都可以和對端建立連接,不管怎樣都無法阻止惡意程序通過猜測接收方地址獲得連接
Binder框架定義了四個角色:Server,Client,ServiceManager(以后簡稱SMgr)以及驅動。
其中 Server,Client,SMgr運行于用戶空間,驅動運行于內核空間。這四個角色的關系和互聯網類似:Server是服務器,Client是客戶終端,SMgr是域名服務器(DNS),驅動是路由器。
Android進程間通信的底層,都是靠binder驅動傳輸信息, 如圖:
第一步,Server給Binder實體登記
和DNS類似,SMgr的作用是將字符形式的Binder名字轉化成Client中對該Binder的引用,使得Client能夠通過Binder名字獲得對Server中Binder實體的引用。注冊了名字的Binder叫實名Binder,就象每個網站除了有IP地址外都有自己的網址
。 Server創建了Binder實體,為其取一個字符形式,可讀易記的名字,將這個Binder連同名字以數據包的形式通過Binder驅動發送給 SMgr,通知SMgr注冊一個名叫張三的Binder,它位于某個Server中。驅動為這個穿過進程邊界的Binder創建位于內核中的實體節點以及 SMgr對實體的引用,將名字及新建的引用傳遞給SMgr。SMgr收數據包后,從中取出名字和引用填入一張查找表中。
第二步,Client獲取Binder實體
Server向SMgr注冊了Binder實體及其名字后,Client就可以通過名字獲得該Binder的引用了。Client也利用保留的0號引用向SMgr請求訪問某個Binder:我申請獲得名字叫張三的Binder的引用。
SMgr收到這個連接請求,從請求數據包里獲得Binder的名字,在查找表里找到該名字對應的條目,從條目中取出Binder的引用,將該引用作為回復發送給發起請求的Client。從面向對象的角度,這個Binder對象現在有了兩個引用:一個位于SMgr中,一個位于發起請求的Client中。
如果接下來有更多的Client請求該Binder,系統中就會有更多的引用指向該Binder,就象java里一個對象存在多個引用一樣。而且類似的這些指向Binder的引用是強類型,從而確保只要有引用 Binder實體就不會被釋放掉。。
處理多線程的時候,Android繼承了java的消息隊列機制。
Android系統的消息隊列和消息循環都是針對具體線程的,一個線程可以存在(當然也可以不存在)一個消息隊列和一個消息循環(Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。但是創建的工作線程默認是沒有消息循環和消息隊列的,如果想讓該線程具有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然后調用Looper.loop()進入消息循環。
在android中,大部分的應用程序進程都是由zygote來創建的,為什么用大部分,因為還有一些進程比如系統引導進程、init進程等不是有zygote創建的。相反,zygote還是在init進程之后才被創建的。
注:init進程是盤古開天地級別的進程。
zygote在android中主要有兩個作用:
建立運行時環境并啟動虛擬機,
為應用程序創建DVM進程。
啟動SystemServer:
啟動應用進程:
Zygote進程運行示意圖
1,SystemService的啟動是在Zygote進程創建好后進行的,并且由Zygote進程建立好DVM運行環境,加載ZygoteInit的main函數,最終調用Zygote的本地方法forkSystemServer,并執行linux的fork方法創建SystemServer進程。
2,應用程序的進程也是由Zygote創建的,在ActivityManagerService中的startProcessLocked中調用了Process.start()方法。并通過連接調用Zygote的native方法forkAndSpecialize,執行fork任務
ActivityThread啟動過程簡要序列圖
PackagemanagerService主要管理apk,其實就是管理其中的組件等,如Activiey、Service,從apk中解析其中的組件,保存到相關結構中,以使得后面可以通過相關的接口可以查詢系統安裝組件,apk的安裝,卸載,刪除都是由PackageManagerService負責的。
簡言之:PMS 掌管APK的生死,手里有本生死簿,類于閻王。
(1)WMS:WindowManager Service. Android上發生的事件,例如,觸屏,按鈕什么的都是由WMS獲取的。并且WMS負責了窗口的顯示和控制。
(2)AMS:ActivityManager Service. 總共有三部分的功能。
1.activity的管理調度,但是只是在全局負責activity的管理和組織,任何activty的啟動,都需要提前通知AMS,并由其進行調度但是不干涉activity內部的東西
2.內存管理,有的時候,activity過多,可能會導致內存不夠,AMS會根據內存情況,決定殺死某個 activity。
3.進程管理,AMS會提供API供用戶查詢當前activity的進程信息。
另外包括了兩個消息處理的類KeyQ和InputDispatcherThread,前者是WMS的內部類,當它有一個對象建立的時候,將會監聽UI上所有的用戶操作,包括觸屏,按鍵等,并且把消息放到隊列當中,等待應用的調用。后者的話主要負責從前者放入的消息隊列(QueueEvent)當中獲取相應的消息并且以一定規則予以消息的過濾,并且發放到相應的應用程序當中,類的作用可以顧名思義。
(3)View
View是什么了,每個人都有自己的理解。在Android的官方文檔中是這樣描述的:這個類表示了用戶界面的基本構建模塊。一個View占用了屏幕上的一個矩形區域并且負責界面繪制和事件處理。View是用來構建用戶界面組件(Button,Textfields等等)的基類。ViewGroup子類是各種布局的基類,它是個包含其他View(或其他ViewGroups)和定義這些View布局參數的容器。
客戶端中的線程
包含有Activity的客戶端程序至少包含3個線程,(每個Binder對應一個線程)
1、UI主線程
2、ApplicationThread對象(繼承自Binder)(負責AmS的IPC調用)
3、ViewRoot.W對象(繼承自Binder) (負責WmS的IPC調用)
Android生態系統工作原理圖:
分三步講解整個過程:
apk程序的運行過程 (一) 前期準備
(看上面大圖的中上角,或者看下面的局部截圖)
首先,ActivityThread從main()函數開始執行,調用prepareMainLooper()為UI線程創建一個消息隊列(MessageQueue)。
然后創建一個ActivityThread對象,在ActivityThread的初始化代碼中會創建一個H(Handler)對象和一個ApplicationThread(Binder)對象。其中Binder負責接收遠程AmS的IPC調用,接收到調用后,則通過Handler把消息發送到消息隊列中,UI主線程會異步的從消息隊列中取出消息并執行相應的操作,比如start stop pause等。
接著UI主線程調用Looper.loop()方法進入消息循環體,進入后就會不斷的從消息隊列中讀取并處理消息。
apk程序的運行過程 (二)啟動Activity
(看上面大圖的中間部分,或者看下面的局部截圖)
當ActivityThread接收到AmS發送start某個Activity后,就會創建指定的Activity對象,Activity又會創建PhoneWindow類——>DecorView類——>創建相應的View或者ViewGroup。
創建完成后,Activity需要把創建好的界面顯示到屏幕上,于是調用WindowManager類,后者于是創建一個ViewRoot對象,該對象實際上創建了ViewRoot類和W類,創建ViewRoot對象以后,WindowManager再調用WmS提供的遠程調用接口完成添加一個窗口并顯示到屏幕上。
apk程序的運行過程(三) 響應用戶屏幕操作
(看上面大圖最左側,或者看下面的局部截圖)
接下來,用戶開始在程序界面上操作,KeyQ線程不多把用戶消息存儲到QueueEvent隊列中,InputDispatcherThread線程逐個取出消息,然后調用WmS中的相關函數處理該消息,當WmS發現該消息屬于客戶端某個窗口時,就會調用相應的窗口W接口。
W類是一個Binder,負責接收WmS的IPC調用,并把調用消息傳遞給ViewRoot,ViewRoot再把消息傳遞給UI主線程ActivityThread,ActivityThread解析該消息并作相應的處理,在客戶端程序中,首先處理消息的是DecorView,如果DecorView不想處理該消息,則可以把該消息傳遞給其內部包含的子View或者ViewGroup,如果還沒有處理,則傳遞給PhoneWindow,最后在傳遞給Activity。
本文僅從總體概念和基本原理上,介紹了Android系統的基本架構、核心功能組件和工作原理,由于篇幅所限,不可能就每章每點都詳細講解,只是蜻蜓點水,一掠而過,只希望能激發初學者的好奇心,通過本文所撕開的Android外衣的一角,讓你窺到一點秘密,激起你對Android的興趣。如果想繼續深入了解Android的深層原理,還需要大家一起研究學習討論。讓我們一起,繼續向Android的最高殿堂前進!
—— 空谷幽蘭 2014-7-7
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。