今天說說神秘又常用又多變的Binder~
- Binder是什么
- Binder通信程序和原理
- 在Android中的應用
- Binder優勢
Binder是什么
先借用神書《Android開發藝術探索》中的一段話:
直觀的說,Binder是一個類,實作了IBinder介面,
從IPC(Inter-Process Communication,行程間通信)角度來說,Binder是Android中一種跨行程通信方式,
還可以理解為一種虛擬的物理設備,它的設備驅動是/dev/binder,
從Android FrameWork角度來說,Binder是ServiceManager連接各種Manager(ActivityManager,WindowManager等等)和回應ManagerService的橋梁,
從Android應用層來說,Binder是客戶端和服務端進行通信的媒介,
挺多概念的是吧,其實就說了一件事,Binder就是用來行程間通信的,是一種IPC方式,后面所有的解釋都是Binder實際應用涉及到的內容,
不管是獲取其他的系統服務,亦或是服務端和客戶端的通信,都是源于Binder的行程間通信能力,
Binder通信程序和原理
首先,還是看一張圖,原圖也是出自神書中:

首先要明確的是客戶端行程是無法直接操作服務端中的類和方法的,因為不同行程直接是不共享資源的,所以客戶端這邊操作的只是服務端行程的一個代理物件,也就是一個服務端的類參考,也就是Binder參考,
總體通信流程就是:
- 客戶端通過代理物件向服務器發送請求,
- 代理物件通過
Binder驅動發送到服務器行程 - 服務器行程處理請求,并通過
Binder驅動回傳處理結果給代理物件 - 代理物件將結果回傳給客戶端,
再看看在我們應用中常常用到的作業模型,上圖:

這就是在應用層面我們常用的作業模型,通過ServiceManager去獲取各種系統行程服務,這里的通信程序如下(詳細流程也可參考文末鏈接):
- 服務端跨行程的類都要繼承
Binder類,所以也就是服務端對應的Binder物體,這個類并不是實際真實的遠程Binder物件,而是一個Binder參考(即服務端的類參考),會在Binder驅動里還要做一次映射, - 客戶端要呼叫遠程物件函式時,只需要呼叫
Binder參考的方法,一般是transact函式, - 然后Binder參考會把資料放入到Client的共享記憶體,
Binder驅動從Client的共享記憶體中讀取資料,根據這些資料找到對應的遠程行程的共享記憶體, - 然后把資料拷貝到遠程行程的共享記憶體中,并通知遠程行程執行onTransact()函式,這個函式也是屬于
Binder類, - 遠程行程
Binder物件執行完成后,將得到的寫入自己的共享記憶體中,Binder驅動再將遠程行程的共享記憶體資料拷貝到客戶端的共享記憶體,并喚醒客戶端執行緒,
所以通信程序中比較重要的就是這個服務端的Binder參考,通過它來找到服務端并與之完成通信,
看到這里可能有的人疑惑了,圖中執行緒池怎么沒用到啊?
- 可以從第一張圖中看出,
Binder執行緒池位于服務端,它的主要作用就是將每個業務模塊的Binder請求統一轉發到遠程Servie中去執行,從而避免了重復創建Service的程序,也就是服務端只有一個,但是可以處理多個不同客戶端的Binder請求,
在Android中的應用
Binder在Android中的應用除了剛才的ServiceManager,你還想到了什么呢?
- 系統服務是用過
getSystemService獲取的服務,內部也就是通過ServiceManager,例如四大組件的啟動調度等作業,就是通過Binder機制傳遞給ActivityManagerService,再反饋給Zygote,而我們自己平時應用中獲取服務也是通過getSystemService(getApplication().WINDOW_SERVICE)代碼獲取, AIDL(Android Interface definition language),例如我們定義一個IServer.aidl檔案,aidl工具會自動生成一個IServer.java的java介面類(包含Stub,Proxy等內部類),- 前臺行程通過
bindService系結后臺服務行程時,onServiceConnected(ComponentName name, IBinder service)傳回IBinder物件,并且可以通過IServer.Stub.asInterface(service)獲取IServer的內部類Proxy的物件,其實作了IServer介面,
Binder優勢
在Linux中,行程通信的方式肯定不止Binder這一種,還有以下這些:
管道(Pipe)
信號(Signal)
訊息佇列(Message)
共享記憶體(Share Memory)
套接字(Socket)
Binder
而Binder在這之后主要有以下優點:
性能高,效率高:傳統的IPC(套接字、管道、訊息佇列)需要拷貝兩次記憶體、Binder只需要拷貝一次記憶體、共享記憶體不需要拷貝記憶體,安全性好:接收方可以從資料包中獲取發送發的行程Id和用戶Id,方便驗證發送方的身份,其他IPC想要實驗只能夠主動存入,但是這有可能在發送的程序中被修改,
熟悉Zygote的朋友可能知道,在fork()行程的時候,也就是向Zygote行程發出創建行程的訊息的時候,用到的行程間通信方式就不是Binder了,而換成了Socket,這主要是因為fork不允許存在多執行緒,Binder通訊偏偏就是多執行緒,
所以具體的情況還是要去具體選擇合適的IPC方式,
參考
https://www.cnblogs.com/hustcser/p/10228843.html
拜拜
有一起學習的小伙伴可以關注下??我的公眾號——碼上積木,每天剖析一個知識點,我們一起積累知識,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/229014.html
標籤:Android
下一篇:fs_tab檔案的決議

