android面試(6)-Binder機制
一直說,要寫一篇關於Binder的詳解,今天終於發福利了~
說到Binder,真的是頭大,因為它涉及到的知識點實在是太多,所以在這裡,我不準備總結太底層的東西,原因嘛,就是因為我也還沒搞清楚,哈哈~~;
好了,言歸正傳,要想了解Binder,首先得了解一些Linux核心的基礎知識:
1.Linux核心基礎知識:
(1)使用者空間/核心空間:
一切從簡,使用者空間指的是使用者程式所執行的空間,核心空間是 Linux 核心的執行空間,為了安全,它們是隔離的,即使使用者的程式崩潰了,核心也不受影響。
(2)系統呼叫
Linux將使用者空間和核心空間隔離是有其道理的,使用者軟體良莠不齊,要是它們亂搞把系統玩壞了怎麼辦?因此對於某些特權操作必須交給安全可靠的核心來執行。
但是雖然是隔離的,但是總有一些使用者軟體需要訪問核心空間,比如應用程式訪問檔案,網路是很常見的事情,怎麼辦呢?
使用者空間訪問核心空間的唯一方式就是系統呼叫;通過這個統一入口介面,所有的資源訪問都是在核心的控制下執行,以免導致對使用者程式對系統資源的越權訪問,從而保障了系統的安全和穩定。
(3)Binder驅動:
通過系統呼叫,使用者空間可以訪問核心空間,那麼如果一個使用者空間想與另外一個使用者空間進行通訊怎麼辦呢?很自然想到的是讓作業系統核心新增支援;傳統的 Linux 通訊機制,比如 Socket,管道等都是核心支援的;但是 Binder 並不是 Linux 核心的一部分,它是怎麼做到訪問核心空間的呢? Linux 的動態可載入核心模組(Loadable Kernel Module,LKM)機制解決了這個問題;模組是具有獨立功能的程式,它可以被單獨編譯,但不能獨立執行。它在執行時被連結到核心作為核心的一部分在核心空間執行。這樣,Android系統可以通過新增一個核心模組執行在核心空間,使用者程序之間的通過這個模組作為橋樑,就可以完成通訊了。
在 Android 系統中,這個執行在核心空間的,負責各個使用者程序通過 Binder 通訊的核心模組叫做 Binder 驅動;
瞭解了這些概念之後,接下來正式進入Binder機制的介紹:
2.Binder機制:
首先我們思考一個問題:我們知道,Android使用的Linux核心擁有著非常多的跨程序通訊機制,比如說,socket,管道之類的,那麼為什麼還要單獨為Android創造一個Binder呢?
總結來說,有兩個原因:
(1)出於效能上的考慮:Android是移動裝置,相比於PC機的效能會有差距,在移動裝置上進行頻繁的跨程序通訊本身就是一個極大的考驗,Binder相比較於傳統的socket/管道通訊而言,更加高效,它在IPC時,只需要資料拷貝1次,而傳統的socket之類的需要2次;
(2)出於安全上的考慮:傳統的程序間通訊對於通訊雙方的身份沒有進行嚴格的驗證,只有上層協議才會進行架構,比如說,socket通訊時,IP地址是手動填寫的,可以進行人為的偽造,而Binder支援通訊雙方進行身份校驗,極大的保障了安全性;
第二,我們來談一談Binder的通訊模型:
我們其實可以程序通訊的雙方一方稱為服務端程序,另一方稱為客戶端程序,我們知道,由於程序隔離的存在,在不進行程序間通訊的方式的情況下,客戶端程序是無法訪問服務端程序的;
可以舉個例子:A和B要打電話,A首先要有B的電話號碼,電話號碼在通訊錄獲取,通訊錄中儲存了B的暱稱,電話號碼之類的資訊,得到電話號碼之後,還需要電話基站的支援,A和B才可以進行電話交流;這裡,我們發現,一次簡單的打電話的過程,除了A和B兩個主體物件外,還存在兩個隱含的但是必不可少的東西,通訊錄和電話基站;
從上面的基礎知識我們可以知道,兩個程序之間如果需要進行通訊,那麼就必須需要核心的幫助,而這個核心模組就是Binder驅動。
我們可以做個類比,對於A和B相當於兩個程序,他們要打電話就相當於要進行通訊,其中電話基站就想到與Binder驅動,而通訊錄則相當於其中的一個ServerManager
ServerManager其實就是一個程序,它裡面維護了一張表,表裡面儲存的是向他註冊過的程序資訊,在通訊之初,首先需要有一個程序向驅動申請成為ServerManager,當核心驅動同意之後,這個成為ServerManager的程序就負責管理所有需要通訊的程序資訊,當客戶端程序要訪問服務端程序時,服務端程序首先會向ServerManager註冊,讓ServerManager儲存自己的有關資訊,當ServerManger儲存完畢後,客戶端程序就會通過Binder驅動向ServerManger查詢服務端程序的資訊,ServerManage就會將服務端程序的資訊返回給客戶端程序,客戶端與服務端程序之間就可以通過這些資訊,利用Binder驅動來進行通訊了;
所以,總結來說,Binder通訊機制分三步:
第一步:ServerManager在其內部維護一張表;
第二步:服務端程序向ServerManager註冊資訊;
第三步:客戶端程序向ServerManager取得資訊,通過Binder驅動與服務端程序通訊;
這裡我們一直強調通過Binder驅動進行通訊,但是Binder的通訊原理到底是什麼呢?這裡有點繞。
如上圖,客戶端想呼叫服務端的的add方法,返回一個Object物件
首先,Server會先向SeverManager註冊一張表,這個表中就儲存了相關資訊,告訴ServerManager我這裡有一個返回值為Object的add方法,
client向ServerManager中查詢Server端有沒有一個返回值為Object的add方法,由於程序之間的通訊都是在核心中進行的,驅動會在資料傳輸時做一些手腳,不會返回給client真正的server的Object的物件,而是返回一個代理物件,這個代理物件裡包含了一個add方法,要注意,代理物件的add方法是一個空方法,它唯一要做的只是需要將引數包裝好之後交給核心驅動來實現
Binder驅動收到代理物件的add方法之後,會在ServerManager表中查詢存在有這個方法,Binder驅動就會將代理物件替換成server端的物件,呼叫server端的add方法,將結果返回給客戶端。
Binder機制知識我還沒有講的很精細,但是大致輪廓差不多有了,最後,說了這麼久,到底什麼是Binder呢?在我看來啊,大致有三種角度來理解:
(1)通常意義上來說,Binder就是指Andriod的通訊機制;
(2)對於服務端程序來說,Binder指的是Binder本地物件,對於客戶端程序來說,Binder指的是Binder代理物件。
(3)對於傳輸過程來說,Binder是可以進行跨程序傳遞的物件;