Android Binder面試詳解

一、Linux內核的基礎知識

1、進程隔離/虛擬地址空間

2、系統調用

3、Linux跨進程通信機制


目前linux支持的IPC包括傳統的管道、System V IPC、即消息隊列/共享內存/信號量,以及socket中只有socket支持Client-Server的通信方式

1.管道(Pipe)及有名管道(named pipe)

2.信號(Signal)

3.報文(Message)隊列(消息隊列)

4.共享內存

5.信號量(semaphore)

6.套接字(Socket)

二、Binder通信機制

1、為什么使用binder

在上面這些可供選擇的方式中,Android使用得最多也最被認可的還是Binder機制。

因為Binder更加簡潔和快速,消耗的內存資源更小嗎?不錯,這些也正是Binder的優點。

當然,也還有很多其他原因,比如傳統的進程間通信可能會增加進程的開銷,而且有進程過載和安全漏洞等方面的風險,Binder正好能解決和避免這些問題。

Binder主要能提供以下一些功能:

用驅動程序來推進進程間的通信。

通過共享內存來提高性能。

為進程請求分配每個進程的線程池。

針對系統中的對象引入了引用計數和跨進程的對象引用映射。

進程間同步調用。

使用Binder跨進程通訊主要有一下兩個方面

一、性能方面

跨進程通訊中,只有socket支持Client-Server的通信方式,但是socket作為一款通用接口,其傳輸效率低,開銷大,主要用在跨網絡的進程間通信和本機上進程間的低速通信。消息隊列和管道采用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開辟的緩存區中,然后再從內核緩存區拷貝到接收方緩存區,至少有兩次拷貝過程。共享內存雖然無需拷貝,但控制復雜,難以使用。

Android Binder機制原理(史上最強理解,沒有之一)

二、安全性能方面

首先傳統IPC的接收方無法獲得對方進程可靠的UID和PID(用戶ID進程ID),從而無法鑒別對方身份。Android為每個安裝好的應用程序分配了自己的UID,故進程的UID是鑒別進程身份的重要標志。使用傳統IPC只能由用戶在數據包里填入UID和PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標記只有由IPC機制本身在內核中添加。其次傳統IPC訪問接入點是開放的,無法建立私有通道。比如命名管道的名稱,systemV的鍵值,socket的ip地址或文件名都是開放的,只要知道這些接入點的程序都可以和對端建立連接,不管怎樣都無法阻止惡意程序通過猜測接收方地址獲得連接。

基于以上原因,Android需要建立一套新的IPC機制來滿足系統對通信方式,傳輸性能和安全性的要求,這就是Binder。

Binder基于Client-Server通信模式,傳輸過程只需一次拷貝,為發送發添加UID/PID身份,既支持實名Binder也支持匿名Binder,安全性高。


詳情參考鏈接:為什么是binder


2、什么是binder


3、binder通信模型

Binder的通信模型有4個角色:Binder Client、Binder Server、Binder Driver(Binder驅動)、ServiceManager。


可以看到,ServiceManager、Binder Client、Binder Server處于不同的進程,他們三個都在用戶空間,而Binder驅動在內核空間。(我是特意把Binder驅動畫的比較大的,因為Binder驅動的作用最大)

那先來簡述一下這個通信模型:

首先是有一個ServiceManager,剛開始這個通訊錄是空白的,然后Server進程向ServiceManager注冊一個映射關系表,之后Client進程想要和Server進程通信,首先向ServiceManager查詢地址,ServiceManager收到查詢的請求之后,返回查詢結果給Client。

注意到這里不管是Server進程注冊,還是Client查詢,都是經過Binder驅動的,這也真是Binder驅動的作用所在,


4、bind通信機制原理


1. Server進程向ServiceManager注冊,告訴ServiceManager我是誰,我有什么,我能做什么。就好比徐同學(Server進程)有一臺筆記本(computer對象),這臺筆記本有個add方法。這時映射關系表就生成了。

2. Client進程向ServiceManager查詢,我要調用Server進程的computer對象的add方法,可以看到這個過程經過Binder驅動,這時候Binder驅動就開始發揮他的作用了。當向ServiceManager查詢完畢,是返回一個computer對象給Client進程嗎?其實不然,Binder驅動將computer對象轉換成了computerProxy對象,并轉發給了Client進程,因此,Client進程拿到的并不是真實的computer對象,而是一個代理對象,即computerProxy對象。很容易理解這個computerProxy對象也是有add方法,(如果連add方法都沒有,豈不是欺騙了Client?),但是這個add方法只是對參數進行一些包裝而已。

3. 當Client進程調用add方法,這個消息發送給Binder驅動,這時驅動發現,原來是computerProxy,那么Client進程應該是需要調用computer對象的add方法的,這時驅動通知Server進程,調用你的computer對象的add方法,將結果給我。然后Server進程就將計算結果發送給驅動,驅動再轉發給Client進程,這時Client進程還蒙在了鼓里,他以為自己調用的是真實的computer對象的add方法,其實他只是調用了代理而已。不過Client最終還是拿到了計算結果。

好了,一個通信過程就完成了。我們發現,其實Binder驅動就是一個中轉。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容