Android面試集錦系列(10)——神祕的Binder機制
前言
有些東西你一直在用它,但卻一直不知道自己在使用它。在Android的應用開發中,Binder就是這麼一個角色,你編寫的應用都使用過Binder機制(如startActivity的執行過程),但是你卻說不出什麼是Binder,甚至很多人都不知道Binder的存在。
那麼,這種已經融入你的使用但又不讓人發覺的機制對我們做應用開發有用嗎?很多人認為並沒有用,往往在他們的印象裡Binder是和驅動一起出現的,叫“Binder驅動”,而我們做應用層開發的基本上不需要去修改或者開發驅動。這樣一來,Binder對於應用開發者來說就顯得很神祕但是和自己無關。
面試題:Binder是什麼?它是如何實現跨程序通訊的?
Binder的英文原意是“膠水”的意思,其實很形像了。Binder模糊了程序邊界,淡化了程序間通訊的過程,整個系統彷彿運行於同一個面向物件的程式之中。形形色色的Binder物件以及星羅棋佈的引用彷彿粘接各個應用程式的膠水。
要理解Binder當然要先從Linux程序說起。
Linux程序基礎
為了保護程序空間不被別的程序破壞或者干擾,Linux的程序是相互獨立的(程序隔離),而且一個程序空間還分為使用者空間和核心(Kernel)空間,相當於把Kernel和上層的應用程式抽像的隔離開。這裡有兩個隔離,一個程序間是相互隔離的,二是程序內有使用者和核心的隔離。
即然有隔離,那麼它們之前要相互配合時就得有合作(互動)。程序間的互動就叫程序間通訊(IPC,或稱跨程序通訊),而程序內的使用者和核心的互動就是系統呼叫。
使用者空間訪問核心空間的唯一方式就是系統呼叫;通過這個統一入口介面,所有的資源訪問都是在核心的控制下執行,以免導致對使用者程式對系統資源的越權訪問,從而保障了系統的安全和穩定。
也就是說,為了保證安全性和獨立性,一個程序是不能直接操作或者訪問別一個程序空間的。Android即然是架設在Linux基礎之上的,當然也要解決這個程序間通訊的問題。
為什麼要使用Binder?
在傳統的Linux上,我們還是有很多選擇可以用來實現程序間通訊,如管道、SystemV、Socket等。那麼Android為什麼不使用這些原有的技術,而是要使開發一種新的叫Binder的程序間通訊機制呢?
主要有兩個方面的原因:
-
效能方面
在移動裝置上(效能受限制的裝置,比如要省電),廣泛地使用跨程序通訊對通訊機制的效能有嚴格的要求,Binder相對出傳統的Socket方式,更加高效。Binder資料拷貝只需要一次,而管道、訊息佇列、Socket都需要2次,共享記憶體方式一次記憶體拷貝都不需要,但實現方式又比較複雜。
-
安全方面
傳統的程序通訊方式對於通訊雙方的身份並沒有做出嚴格的驗證,比如Socket通訊ip地址是客戶端手動填入,很容易進行偽造,而Binder機制從協議本身就支援對通訊雙方做身份校檢,因而大大提升了安全性。
還有一些好處,如實現面象物件的呼叫方式,在使用Binder時就和呼叫一個本地例項一樣。
Binder執行機制
Binder基於Client-Server通訊模式,除了Client端和Server端,還有兩角色一起合作完成程序間通訊功能。
Binder通訊的四個角色:
- Client程序:使用服務的程序。
- Server程序:提供服務的程序。
- ServiceManager程序:ServiceManager的作用是將字元形式的Binder名字轉化成Client中對該Binder的引用,使得Client能夠通過Binder名字獲得對Server中Binder實體的引用。
- Binder驅動:驅動負責程序之間Binder通訊的建立,Binder在程序之間的傳遞,Binder引用計數管理,資料包在程序之間的傳遞和互動等一系列底層支援。
初次接觸這些概念可能會覺得難於理解,讀者可以把四個角色和熟悉的網際網路進行類比:Server是伺服器,Client是客戶終端,ServiceManager是域名伺服器(DNS),驅動是路由器。這樣類比,你很容易就能理解下圖:

Binder的執行機制就很好理解了,Server程序向Service Manager程序註冊服務(可訪問的方法介面),Client程序通過Binder驅動可以訪問到Server程序提供的服務。Binder驅動管理著Binder之間的資料傳遞,這個資料的具體格式由Binder協議定義(可以類比為網路傳輸的TCP協議)。並且Binder驅動持有每個Server在核心中的Binder實體,並給Client程序提供Binder的引用。
Binder跨程序傳輸並不是真的把一個物件傳輸到了另外一個程序;傳輸過程好像是Binder跨程序穿越的時候,它在一個程序留下了一個真身,在另外一個程序幻化出一個影子(這個影子可以很多個);Client程序的操作其實是對於影子的操作,影子利用Binder驅動最終讓真身完成操作。

Binder的執行緒管理
每個Binder的Server程序會建立很多執行緒來處理Binder請求,可以簡單的理解為建立了一個Binder的執行緒池吧(雖然實際上並不完全是這樣簡單的執行緒管理方式),而真正管理這些執行緒並不是由這個Server端來管理的,而是由Binder驅動進行管理的。
一個程序的Binder執行緒數預設最大是16,超過的請求會被阻塞等待空閒的Binder執行緒。理解這一點的話,你做程序間通訊時處理併發問題就會有一個底,比如使用ContentProvider時(又一個使用Binder機制的元件),你就很清楚它的CRUD(建立、檢索、更新和刪除)方法只能同時有16個執行緒在跑。
Binder對應用開發者的用處
上面提到的執行緒數是一個對應用開發有用的地方,很多人之前由於不瞭解有這個執行緒數的限制可能會在這裡遇到過麻煩。
當然,最重要的是你瞭解了Android的程序間通訊機制,知道Android的元件間是如何實現程序間通訊和資料共享的,當你的應用要處理程序間通訊時,你知道可能要關注哪個方面。如你的Activity元件可以設定在不同的程序中執行,那麼每個程序都是獨立的,它要使用別的程序的資料時,你就會知道用靜態變數去互動沒有意義。而且,理解了原理,再去編寫AIDL的程式碼就沒有那麼難理解了。
對於一些Framework層的開發者,如自已定製ROM的團隊,需要提供自己的系統服務時,Binder機制肯定是必需要了解的,不然無從下手。
小結
多程序問題不是每個開發都會遇到的,很多應用只要在自己的程序內完成業務需求就可以了,但知道多程序的存在,並理解Android提供的Binder機制,那麼我們在選擇如何做程序間的互交時就會更明確可能存在的問題和Android的解決方案。
也許,這幾段講解後,你還是一知半解的,那麼請看下一篇和AIDL相關的實戰。
最後
在這裡我總結出了網際網路公司Android程式設計師面試簡歷模板,面試涉及到的絕大部分面試題及答案做成了文件和架構視訊資料免費分享給大家【 包括高階UI、效能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料 】,希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。
資料獲取方式:加入Android架構交流QQ群聊:513088520 ,進群即領取資料!!!
點選連結加入群聊【Android移動架構總群】: 加入群聊

資料大全