神祕、經常使用、多變的Binder

今天說說神祕又經常使用又多變的Binder~html

  • Binder是什麼
  • Binder通訊過程和原理
  • 在Android中的應用
  • Binder優點

Binder是什麼

先借用神書《Android開發藝術探索》中的一段話:java

直觀的說,Binder是一個類,實現了IBinder接口。

從IPC(Inter-Process Communication,進程間通訊)角度來講,Binder是Android中一種跨進程通訊方式。

還能夠理解爲一種虛擬的物理設備,它的設備驅動是/dev/binder。

從Android FrameWork角度來講,Binder是ServiceManager鏈接各類Manager(ActivityManager,WindowManager等等)和響應ManagerService的橋樑。

從Android應用層來講,Binder是客戶端和服務端進行通訊的媒介。

挺多概念的是吧,其實就說了一件事,Binder就是用來進程間通訊的,是一種IPC方式。後面全部的解釋都是Binder實際應用涉及到的內容。android

不論是獲取其餘的系統服務,亦或是服務端和客戶端的通訊,都是源於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方式。

參考

http://www.javashuo.com/article/p-nfrqcdjw-nw.html

拜拜

有一塊兒學習的小夥伴能夠關注下❤️個人公衆號——碼上積木,天天剖析一個知識點,咱們一塊兒積累知識。

相關文章
相關標籤/搜索