1. 什么是Android IPC
- IPC:inter-process Commnication跨進程的通信,多進程之間的通信,不同的操作系統有不同的通信方式,Android繼承自Linux,但其IPC并沒有完全繼承Linux,除了socket進程通信之外,其最具特色通信方式之一的是binder機制
- 為什么需要進程通信:我們知道Android一般情況下一個應用是默認運行在一個進程中,但有可能一個應用中需要采用多進程模式來實現(比如獲取多份內存空間),或者兩個應用之間需要獲取彼此之間的數據,還有AMS(系統服務)對每個應用中四大組件的管理,系統服務是運行在一個單獨的進程中,這些統統需要IPC
- Android在一個應用中開啟多線程模式
- 為四大組件在Android Manifest中指定Android:process屬性,進程名以 : 開頭的進程屬于當前應用的私有進程,其他應用的組件不可以和它在同一個進程中,進程名不以: 開頭的屬于全局進程,其他應用可以通過ShareUID方式跑在一個進程中,這意味著可以共享內存數據。
- 多進程運行:我們知道Android為每一個進程獨立分配了一個獨立的虛擬機,所以在內存分配上是有不同的地址空間,所以運行在不同進程的四大組件,他們之間沒辦法共享數據,因此我們需要進程間的通信
- Android進程間通信方式包括:通過intent傳遞數據,共享文件和sharedPreference,基于binder的message和AIDL還有socket
2. IPC 基礎概念
Serializable和Parcelable接口可以完成對象的序列化。
序列化是指將一個對象轉化為二進制或者是某種格式的字節流,將其轉換為易于保存或網絡傳輸的格式的過程,反序列化則是將這些字節重建為一個對象的過程。
在Android中,intent和Binder在傳輸數據的時候就需要將對象實現parcelable或者serializable接口。
-
Serializable接口:
- Java提供的序列化接口,使用時只需要實現Serializable接口并聲明一個serialVersionUID(用于反序列化)
- 使用方法
Parcelable接口:
Android中Parcelable接口用法兩者都可以實現序列化并可用于intent間的數據傳遞,Serializable使用簡單,但是開銷很大,Parcelable是Android中的序列化方式,使用起來麻煩一點,但是效率很高,是Android推薦的方式。Parcelable主要用在內存序列化上,如果要將對象序列化到存儲設備或者通過網絡傳輸也是可以的,但是會比較復雜,這兩種情況建議使用Serializable。
-
Binder機制:為什么Android 要采用Binder作為IPC機制?
- 性能:Binder數據拷貝只需要一次,而管道、消息隊列和socket都需要2次,共享內存不需要一次內存拷貝,從性能角度來看,binder性能僅次于共享內存。
- 穩定性:Binder基于C/S 架構 ,server端與client端相對獨立,共享內存需要考慮訪問臨界資源的并發同步問題,binder結構的穩定性較好
- 安全性:Android為每個人應用程序分配了自己的UID,進程的UID是鑒別進程身份的重要標志,Android系統中對外只暴露Client端,Client端將任務發送給Server端,Server端會根據權限控制策略
Android OS中的Zygote進程的IPC采用的是Socket(套接字)機制,Android中的Kill Process采用的signal(信號)機制等等。而Binder更多則用在system_server進程與上層App層的IPC交互。
Binder在Android系統中江湖地位非常之高。在Zygote孵化出system_server進程后,在system_server進程中出初始化支持整個Android framework的各種各樣的Service,而這些Service從大的方向來劃分,分為Java層Framework和Native Framework層(C++)的Service,幾乎都是基于BInder IPC機制。
- Java framework:作為Server端繼承(或間接繼承)于Binder類,Client端繼承(或間接繼承)于BinderProxy類。例如ActivityManagerService(用于控制Activity、Service、進程等) 這個服務作為Server端,間接繼承Binder類,而相應的ActivityManager作為Client端,間接繼承于BinderProxy類。 當然還有PackageManagerService、WindowManagerService等等很多系統服務都是采用C/S架構;
- Native Framework層:這是C++層,作為Server端繼承(或間接繼承)于BBinder類,Client端繼承(或間接繼承)于BpBinder。例如MediaPlayService(用于多媒體相關)作為Server端,繼承于BBinder類,而相應的MediaPlay作為Client端,間接繼承于BpBinder類。
3. Android 中的binder
參考:
Binder系列—開篇
可能是講解Binder機制最好的文章
Android Bander設計與實現 - 設計篇
Android - Binder驅動
3.1 面向對象的binder IPC
- Binder使用C/S 模式,一個進程作為server提供諸如視頻解碼,網絡連接、查詢等多種服務,多個進程作為client向server發起服務請求,獲得所需要的服務。
- Binder的獨特之處在于Binder對象是一個可以跨進程實現的的對象,它的實體位于一個進程中,而它的引用則在其他client進程中,Binder驅動為面向對象的進程間通信提供底層支持。
3.2 Binder通信框架
Binder框架定義了四個角色,Server,Client,ServiceManager,以及binder驅動,驅動運行在內核空間,其他三者運行在用戶空間。
- Binder 驅動:binder驅動與硬件設備沒有關系,但是它的工作方式與設備驅動程序是一樣的,工作在內核態,提供open(),mmap(),ioctl等標準文件操作,用戶可以通過/dev/binder來訪問它,驅動負責進程之間binder通信的建立,傳遞,計數管理以及數據的傳遞交互等底層支持。
- ServiceManager:將Binder名字轉換為client中對該binder的引用,使得client可以通過binder名字獲得server中binder實體的引用。
- Client和Server在Binder驅動和Service Manager提供的基礎設施上,進行Client-Server之間的通信
- Server創建了Binder實體,為其取一個字符形式,可讀易記的名字,將這個Binder連同名字以數據包的形式通過Binder驅動發送給SMgr,通知SMgr注冊一個名叫張三的Binder,它位于某個Server中。驅動為這個穿過進程邊界的Binder創建位于內核中的實體節點以及SMgr對實體的引用,將名字及新建的引用打包傳遞給SMgr。SMgr收數據包后,從中取出名字和引用填入一張查找表中。
- Server向SMgr注冊了Binder實體及其名字后,Client就可以通過名字獲得該Binder的引用