Android 的 Binder 機制概念介紹

  結合瞭如下兩篇文章的介紹,對Android 的 Binder 機制概念開始有了必定的理解。分享給你們。

-------------------------------------分割線---------------------------------

摘要

Binder是android 中一個很重要且很複雜的概念,它在系統的總體運做中發揮着極其重要的做用,不過本文並不打算從深層次分析Binder機制,有兩點緣由:1是目前網上已經 有2篇很好的文章了,2是對Binder機制進行深刻底層乃至驅動的分析這一過程至關困難且至關耗時,所以並不適合重複造輪子。本文的角度是對 Android的Binder機制從總體和概念上進行分析,可以讓你們很快明白到底什麼是Binder,Binder是幹什麼的,Binder和應用開發 的關係是什麼,總之,這篇文章仍是很值得去看一看的。

什麼是Binder

1. 直觀來講,Binder是Android中的一個類,它繼承了IBinder接口

2. 從IPC角度來講,Binder是Android中的一種跨進程通訊方式,Binder還能夠理解爲一種虛擬的物理設備,它的設備驅動是/dev/binder,該通訊方式在linux中沒有

3. 從Android Framework角度來講,Binder是ServiceManager鏈接各類Manager(ActivityManager、WindowManager,etc)和相應ManagerService的橋樑

4. 從Android應用層來講,Binder是客戶端和服務端進行通訊的媒介,當你bindService的時候,服務端會返回一個包含了服務端業務調用的 Binder對象,經過這個Binder對象,客戶端就能夠獲取服務端提供的服務或者數據,這裏的服務包括普通服務和基於AIDL的服務

爲何Android內核要使用Binder

Android中有大量的CS(Client-Server)應用方式,這就要求Android內部提供IPC方法,而linux所支持的進程通訊方式有兩個問題:性能和安全性。

目 前linux支持的IPC包括傳統的管道,System V IPC(消息隊列/共享內存/信號量),以及socket,但只有socket支持Client-Server的通訊方式,因爲socket是一套通用的 網絡通訊方式,其傳輸效率低下切有很大的開銷,好比socket的鏈接創建過程和中斷鏈接過程都是有必定開銷的。消息隊列和管道採用存儲-轉發方式,即數 據先從發送方緩存區拷貝到內核開闢的緩存區中,而後再從內核緩存區拷貝到接收方緩存區,至少有兩次拷貝過程。共享內存雖然無需拷貝,但控制複雜,難以使 用。

在安全性方 面,Android做爲一個開放式,擁有衆多開發者的的平臺,應用程序的來源普遍,確保智能終端的安全是很是重要的。終端用戶不但願從網上下載的程序在不 知情的狀況下偷窺隱私數據,鏈接無線網絡,長期操做底層設備致使電池很快耗盡等等。傳統IPC沒有任何安全措施,徹底依賴上層協議來確保。首先傳統IPC 的接收方沒法得到對方進程可靠的UID/PID(用戶ID/進程ID),從而沒法鑑別對方身份。Android爲每一個安裝好的應用程序分配了本身的 UID,故進程的UID是鑑別進程身份的重要標誌。使用傳統IPC只能由用戶在數據包裏填入UID/PID,但這樣不可靠,容易被惡意程序利用。可靠的身 份標記只有由IPC機制自己在內核中添加。其次傳統IPC訪問接入點是開放的,沒法創建私有通道。好比命名管道的名稱,system V的鍵值,socket的ip地址或文件名都是開放的,只要知道這些接入點的程序均可以和對端創建鏈接,無論怎樣都沒法阻止惡意程序經過猜想接收方地址獲 得鏈接。

基於以上原 因,Android須要創建一套新的IPC機制來知足系統對通訊方式,傳輸性能和安全性的要求,這就是Binder。Binder基於 Client-Server通訊模式,傳輸過程只需一次拷貝,爲發送發添加UID/PID身份,既支持實名Binder也支持匿名Binder,安全性 高。下圖爲Binder通訊過程示例:


http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1222/2204.html

---------------------分割線----------------------------


1.Binder通訊機制介紹

這篇文章會先對比Binder機制與Linux的通訊機制的差異,瞭解爲何Android會另起爐竈,採用Binder。接着,會根據 Binder的機制,去理解什麼是Service  Manager,在C/S模型中扮演什麼角色。最後,會從一次完整的通訊活動中,去理解Binder通訊的過程。 html

1.1 Android與Linux通訊機制的比較

雖然Android繼承使用Linux的內核,但Linux與Android的通訊機制不一樣。 linux

在Linux中使用的IPC通訊機制以下: android

  1. 傳統IPC:無名pipe, signal, trace, 有名管道 緩存

  2. AT&T Unix 系統V:共享內存,信號燈,消息隊列 安全

  3. BSD Unix:Socket 服務器

而在Android中,並無使用這些,取而代之的是Binder機制。Binder機制是採用OpenBinder演化而來,在Android中使用它的緣由以下: 網絡

  1. 採用C/S的通訊模式。而在linux通訊機制中,目前只有socket支持C/S的通訊模式,但socket有其劣勢,具體參看第二條。 框架

  2. 有更好的傳輸性能。對比於Linux的通訊機制, socket

    • socket:是一個通用接口,致使其傳輸效率低,開銷大; 性能

    • 管道和消息隊列:由於採用存儲轉發方式,因此至少須要拷貝2次數據,效率低;

    • 共享內存:雖然在傳輸時沒有拷貝數據,但其控制機制複雜(好比跨進程通訊時,需獲取對方進程的pid,得多種機制協同操做)。

  3. 安全性更高。Linux的IPC機制在自己的實現中,並無安全措施,得依賴上層協議來進行安全控制。而Binder機制的 UID/PID是由Binder機制自己在內核空間添加身份標識,安全性高;而且Binder能夠創建私有通道,這是linux的通訊機制所沒法實現的 (Linux訪問的接入點是開放的)。

綜上所述,Android採用Binder機制是有道理的。既然Binder機制這麼多優勢,那麼咱們接下來看看它是怎樣經過C/S模型來實現的。

1.2 Binder在Service服務中的做用

在android中,有不少Service都是經過binder來通訊的,好比MediaServer旗下包含了衆多service:

  •     AudioFlinger 音頻核心服務

  •     AudioPolicyService:音頻策略相關的重要服務

  •     MediaPlayerService:多媒體系統中的重要服務

  •     CameraService:有關攝像/照相的重要服務

Binder在C/S中的流程以下:

  1. Server註冊服務。Server做爲衆多Service的擁有者,當它想向Client提供服務時,得先去Service Manager(之後縮寫成SM)那兒註冊本身的服務。Server能夠向SM註冊一個或多個服務。

  2. Client申請服務。Client做爲Service的使用者,當它想使用服務時,得向SM申請本身所須要的服務。Client能夠申請一個或多個服務。

  3. 當Client申請服務成功後,Client就可使用服務了。

SM一方面管理Server所提供的服務,同時又響應Client的請求併爲之分配相應的服務。扮演的角色至關於月老,兩邊牽線。這種通訊方式的好處是: 一方面,service和Client請求便於管理,另外一方面在應用程序開發時,只需爲Client創建到Server的鏈接,就可花不多時間和精力去實 現Server相應功能。那麼,Binder與這個通訊模式有什麼關係呢?!其實,3者的通訊方式就是Binder機制(例如:Server向SM註冊服 務,使用Binder通訊;Client申請請求,用的是Binder通信)

1.3 Binder通訊機制流程(總體框架)

上圖便是Binder的通訊模型。咱們能夠發現:

  1. Client和Server是存在於用戶空間

  2. Client與Server通訊的實現,是由Binder驅動在內核空間實現

  3. SM做爲守護進程,處理客戶端請求,管理全部服務項。

爲了方便理解,咱們能夠把SM理解成DNS服務器; 那麼Binder Driver 就至關於路由的功能。這裏就涉及到Client和Server是如何通訊的問題。下面對1.2中提到的3個流程進行說明。

1.3.1 Server向SM註冊服務

  1. 首先,XXXServer(XXX表明某個)在本身的進程中向Binder驅動申請建立一個XXXService的Binder的實體,

  2. Binder驅動爲這個XXXService建立位於內核中的Binder實體節點以及Binder的引用,注意,是將名字和新建的引用打包傳遞給SM(實體沒有傳給SM),通知SM註冊一個名叫XXX的Service。

  3. SM收到數據包後,從中取出XXXService名字和引用,填入一張查找表中。

  4. 此時,若是有Client向SM發送申請服務XXXService的請求,那麼SM就能夠在查找表中找到該Service的Binder引用,並把Binder引用(XXXBpBinder)返回給Client。

在進一步瞭解Binder通訊機制以前,咱們先弄清幾個概念。

  1. 引用和實體。這裏,對於一個用於通訊的實體(能夠理解成具備真實空間的Object),能夠有多個該實體的引用(沒有真實空間,能夠理解成實體的 一個連接,操做引用就會操做對應連接上的實體)。若是一個進程持有某個實體,其餘進程也想操做該實體,最高效的作法是去得到該實體的引用,再去操做這個引 用。

  2. 有些資料把實體稱爲本地對象,引用成爲遠程對象。能夠這麼理解:引用是從本地進程發送給其餘進程來操做實體之用,因此有本地和遠程對象之名。

1.3.2 一個問題-如何得到SM的遠程接口

若是你足夠細心,會發現這裏有一個問題:

Sm和Server都是進程,Server向SM註冊Binder須要進程間通訊,當前實現的是進程間通訊卻又用到進程間通訊。這就比如雞生蛋、蛋生雞,但至少得先有其中之一。

巧妙的Binder解決思路:

針對Binder的通訊機制,Server端擁有的是Binder的實體;Client端擁有的是Binder的引用。
若是把SM看做Server端,讓它在Binder驅動一運行起來時就有本身的Binder實體(代碼中設置ServiceManager的Binder 其handle值恆爲0)。這個Binder實體沒有名字也不須要註冊,全部的client都認爲handle值爲0的binder引用是用來與SM通訊 的(代碼中是這麼實現的),那麼這個問題就解決了。那麼,Client和Server中這麼達成協議了(handle值爲0的引用是專門與SM通訊之用 的),還不行,還須要讓SM有handle值爲0的實體纔算大功告成。怎麼實現的呢?!當一個進程調用Binder驅動時,使用 BINDER_SET_CONTEXT_MGR命令(在驅動的binder_ioctl中)將本身註冊成SM時,Binder驅動會自動爲它建立 Binder實體。這個Binder的引用對全部的Client都爲0。


1.3.3 Client從SM得到Service的遠程接口


Server向SM註冊了Binder實體及其名字後,Client就能夠經過Service的名字在SM的查找表中得到該Binder的引用了 (BpBinder)。Client也利用保留的handle值爲0的引用向SM請求訪問某個Service:我申請訪問XXXService的引用。 SM就會從請求數據包中得到XXXService的名字,在查找表中找到該名字對應的條目,取出Binder的引用打包回覆給client。之 後,Client就能夠利用XXXService的引用使用XXXService的服務了。
若是有更多的Client請求該Service,系統中就會有更多的Client得到這個引用。

1.3.4 創建C/S通路後

首先要理清一個概念:client擁有本身Binder的實體,以及Server的Binder的引用;Server擁有本身Binder的實體,以及Client的Binder的引用。咱們也能夠從接收方和發送方的方式來理解:

  • 從client向Server發數據:Client爲發送方,擁有Binder的實體;Server爲接收方,擁有Binder的引用

  • 從server向client發數據:Server爲發送方,擁有Binder的實體;client爲接收方,擁有Binder的引用。

也就是說,咱們在創建了C/S通路後,無需考慮誰是Client誰是Server,只要理清誰是發送方誰是接收方,就能知道Binder的實體和引用在哪邊。


創建CS通路後的流程:(當接收方得到Binder的實體,發送方得到Binder的引用後)

  1. 發送方會經過Binder實體請求發送操做。

  2. Binder驅動會處理這個操做請求,把發送方的數據放入寫緩存(binder_write_read.write_buffer) (對於接收方爲讀緩衝區),並把read_size(接收方讀數據)置爲數據大小(對於具體的實現後面會介紹);

  3. 接收方以前一直在阻塞狀態中,當寫緩存中有數據,則會讀取數據,執行命令操做

  4. 接收方執行完後,會把返回結果一樣用binder_transaction_data結構體封裝,寫入寫緩衝區(對於發送方,爲讀緩衝區)

1.3.5 匿名Binder

以前在介紹Android使用Binder機制的優勢中,提到Binder能夠創建點對點的私有通道,匿名Binder就是這種方式。在 Binder通訊中,並非全部用來通訊的Binder實體都須要註冊給SM廣而告之的,Server能夠經過已創建的實體Binder鏈接將建立的 Binder實體傳給Client。而這個Binder沒有向SM註冊名字。這樣Server與Client的通訊就有很高的隱私性和安全性。

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0319/2619.html

相關文章
相關標籤/搜索