文章目錄
什麼是Binder
binder是Android中特有的一種跨進程的實現方式,模糊了進程邊界,淡化了進程通訊的過程,整個系統彷彿運行在OOP
的程序中,Binder
彷彿是粘貼各種應用程序的 “膠水”,英文中binder的意思就是"膠水"。Binder無處不在,就好比在OOP
中,調用的時候使用binder
就可以拿到其他的一些進程服務。如媒體播放,音視頻捕獲,手機傳感器,加速度,方位,溫度,亮度,甚至startActivity/Service等等,都是由不同的服務端 Server
提供一些服務,供應用程序調用,而應用程序作爲客戶端與提供服務的Server
建立鏈接,便可以方便的使用這些服務。
Binder與AIDL關係
平時項目中,如果純粹使用Binder調動系統服務,代碼量會非常大,非常複雜。而AIDL
是一種架構,爲我們使用Binder的時候提供更加輕便簡潔的語法就可以調用Binder,實現跨進程的通信。
AIDL
是專門爲Binder設計的一種框架, 如果單純用Binder來調用系統提供的服務,代碼量會非常大、非常複雜,而AIDL是一中框架,提供給開發者更加輕便的解決跨進程方案,AIDL只是封裝了。如startActivity
封裝了AIDL,一行代碼實現了跨進程。
Binder更貼切的比喻
如上圖:
- Binder :系統提供了很多服務應用程序調用,而Binder作爲了調用這些服務的
接入點
- Client :應用程序作爲
client
,調用系統提供的服務,可以通過binder
,在client而言,binder可以看做通向服務管道的入口
域名發佈的時候,就會告訴DNS(域名解析服務器)真實ip地址。
Binder由來
linux內核提供了很多進程間通信(IPC)的嘗試方式。如下
linux提供的通訊方式 | 缺點 | 其他 |
---|---|---|
管道 | 耗費性能 | 半雙工,如對講機;全雙工,如電話 |
共享內存 | 使多個進程訪問同一塊內存空間,管理混亂。 | |
socket | 適用於網絡通訊,但對於進程間通訊大材小用。 | 適用於網絡通信 |
A進程與B進程通信:
- 管道:首先A打開管道,B打開管道,A往管道中寫數據,進程B從管道中讀數據,不停地寫不停地讀,直到寫完之後,進程A再關閉通道,進程B關閉通道,最後刪除管道。 這個過程很 消耗性能。
- 共享內存 : 多個進程可以同時共享同一塊內存空間,但是管理很混亂。
- socket :更加適用於網絡通信,但對於進程間通訊大材小用。
上圖中,數據會進行至少2次拷貝。
Android應用程序之間,是不可以進行數據共享的,而在底層內核空間就可以。
Android 爲什麼用Binder進行 ipc,
binder會對通信的應用雙方進行身份校驗,安全性高。
android系統會爲每一個應用程序分配一個唯一的UID
,進程的UID是鑑別進程身份的重要標識。
驗證pid(進程id) uid(用戶id)。
傳輸效率高,binder驅動的內核區域進行數據拷貝,只會拷貝一次。
性能僅次於共享內存。
binder基於c/s架構(一對多)
爲發送方添加了pid,uid(Android9.0源碼startActivity有體現,待驗證)。
爲什麼學binder
Binder四個重要的角色:Server , Client ,ServiveManager , Binder驅動
,前三者存在於用戶空間,而Binder驅動存在於內核空間。而用戶空間(client)是不可以進程通信的,內核空間可以。
ServiveManager
服務主要是作爲Server
與 Client
之間的橋樑,ServiceManager
在init
進程中啓動,類比於DNS。Client可以通過ServiceManager拿到Server中Binder實體的引用。如有服務需要提供給client,那需要將binder的引用註冊到ServiceManager中。如client想要使用該服務,需要固定的key(類比於域名www.baidu.com)及binder引用來訪問該服務。從ServiceManager
的map鏈表提取出來,通過key拿到對應的binder引用。
Android中,很多服務都是通過Binder去和AMS進行交互的。如獲取音量服務。
AudioManager audioManager = (AudioManager) getSystemService(Service.AUDIO_SERVICE);
系統提供的很多服務Server
,如手機傳感器、加速度等等,都需要在ServiveManager
中進行註冊,多個系統服務在ServiveManager
中進行註冊。此時,ServiveManager
作爲服務端,而Server
作爲客戶端。
// 當一個進程使用 binder.setContext
Binder驅動:負責進程之間Binder 通訊的建立,binder之間無法直接進行交互,都是+通過Binder驅動進行通訊。binder驅動中有一個線程池,因爲可能存在併發,線程池由binder驅動管理。一個進程中,binder的線程池中線程數最大是16
,超過這請求就會阻塞等待空閒。
ThreadPool:多個需求方需要用個同一個服務或多個服務的時候就產生很多binder驅動的交互。
AIDL
AIDL: Android Interface Definition Language
Client 與 Server進行通信的時候,必須統語言,否則無法進行通信。而AIDL專門爲這種通信 設計的一種架構,用來binder之間通信。
Binder四個重要對象:
Binder角色 | 作用 | 說明 |
---|---|---|
IBinder | 接口,代表了跨進程通訊的能力,只要實現改接口就可以進行跨進程傳輸了。 | |
IInterface | 代表了Server進程對象具備哪些功能,提供哪些方法,對應了AIDL定義的接口 | |
Binder | java層的Binder類,代表了Binder的本地對象,BinderProxy是Binder內部類。 | 繼承自IBinder |
Stub | AIDL的時候,idea自動生成一個stub的靜態內部類,繼承了Binder,實現了IInterface接口 | 具備Serve承諾給Client的一種能力 |
Binder : client訪問server提供的服務的時候,並不是直接操作binder對象而是操作binder引用,並且是通過本地代理BinderProxy 去 操作binder驅動操作來訪問Server,完成之後BinderProxy 就會和內核的內存映射存在共存(共享內存?有待商榷)關係。如下圖:
無論Binder
還是BinderProxy
都是繼承自IBinder
因而皆具備跨進程通信的能力。
Binder機制通信的流程:
總結:
架構設計:
client 代用 代理BinderProxy接口的方法時候,會將Client傳遞的數據打包成Parcel
Parcel Parcelable Searilable
區別