Binder簡介

1、Binder是android重要的IPC通信,與傳統的IPC(Linux 內存共享,管道,信號量,消息隊列,socket等)通信相比,有以下特色:java

一、簡潔快速android

二、內存消耗小緩存

三、進程開銷小安全

四、傳輸性能高,傳輸過程只需一次拷貝(共享內存的方式)服務器

五、進程間同步調用(socket是異步),Binder對象是一個能夠跨進程引用的對象,它的實體位於一個進程中,而它的引用卻遍及於系統的各個進程之中,經過Binder對象調用其提供的方法和調用其它任何本地對象的方法並沒有區別。網絡

六、傳輸安全性高,Binder是基於Client-Server通訊模式,爲發送發添加UID/PID身份,既支持實名Binder也支持匿名Binder,安全性高(傳統IPC沒有任何安全措施,如socket的ip地址或文件名都是開放的,)框架

其中最重要的是傳輸性能高,安全性強,能夠同步調用。異步

(socket做爲一款通用接口,其傳輸效率低,開銷大,主要用在跨網絡的進程間通訊和本機上進程間的低速通訊)socket

 

2、binder與傳統IPC方式數據拷貝次數對比性能

                                      表 1

IPC

數據拷貝次數

共享內存

0

Binder

1

Socket/管道/消息隊列

2

 3、Binder只需一次拷貝的‘祕密’

  Binder採用的內存映射和接收緩存區管理策略:由Binder驅動負責管理數據接收緩存。Binder驅動實現了mmap()系統調用,是用來建立數據接收的緩存空間,mmap()的使用以下:

fd = open("/dev/binder", O_RDWR);

mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);

這樣Binder的接收方就有了一片大小爲MAP_SIZE的接收緩存區。mmap()的返回值是內存映射在用戶空間的地址,不過這段空間是由驅動管理,用戶沒必要也不能直接訪問(映射類型爲PROT_READ,只讀映射)。接收緩存區映射好後就能夠作爲緩存池接收和存放數據了。驅動爲接收方分擔了最爲繁瑣的任務在效率上,因爲mmap()分配的內存是映射在接收方用戶空間裏的,全部整體效果就至關於對有效負荷數據作了一次從發送方用戶空間到接收方用戶空間的直接數據拷貝,省去了內核中暫存這個步驟,提高了一倍的性能。爲了實現用戶空間到用戶空間的拷貝,mmap()分配的內存除了映射進了接收方進程裏,還映射進了內核空間。因此調用copy_from_user()將數據拷貝進內核空間也至關於拷貝進了接收方的用戶空間,這就是Binder只需一次拷貝的‘祕密’

 

4、Binder 通訊模型

Binder框架定義了四個角色:Server,Client,ServiceManager(之後簡稱SMgr)以及Binder驅動。其中Server,Client,SMgr運行於用戶空間,驅動運行於內核空間。這四個角色的關係和互聯網相似:Server是服務器,Client是客戶終端,SMgr是域名服務器(DNS),驅動是路由器。

 

3.1 Binder 驅動

和路由器同樣,Binder驅動雖然默默無聞,倒是通訊的核心。儘管名叫‘驅動’,實際上和硬件設備沒有任何關係,只是實現方式和設備驅動程序是同樣的。它工做於內核態,驅動負責進程之間Binder通訊的創建,Binder在進程之間的傳遞,Binder引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。

3.2 ServiceManager 與實名Binder

和DNS相似,SMgr的做用是將字符形式的Binder名字轉化成Client中對該Binder的引用,使得Client可以經過Binder名字得到對Server中Binder實體的引用。註冊了名字的Binder叫實名Binder,就象每一個網站除了有IP地址外還有本身的網址。Server建立了Binder實體,爲其取一個字符形式,可讀易記的名字,將這個Binder連同名字以數據包的形式經過Binder驅動發送給SMgr,通知SMgr註冊一個名叫張三的Binder,它位於某個Server中。驅動爲這個穿過進程邊界的Binder建立位於內核中的實體節點以及SMgr對實體的引用,將名字及新建的引用打包傳遞給SMgr。SMgr收數據包後,從中取出名字和引用填入一張查找表中。

細心的讀者可能會發現其中的蹊蹺:SMgr是一個進程,Server是另外一個進程,Server向SMgr註冊Binder必然會涉及進程間通訊。當前實現的是進程間通訊卻又要用到進程間通訊,這就好象蛋能夠孵出雞前提倒是要找只雞來孵蛋。Binder的實現比較巧妙:預先創造一隻雞來孵蛋:SMgr和其它進程一樣採用Binder通訊,SMgr是Server端,有本身的Binder對象(實體),其它進程都是Client,須要經過這個Binder的引用來實現Binder的註冊,查詢和獲取。SMgr提供的Binder比較特殊,它沒有名字也不須要註冊,當一個進程使用BINDER_SET_CONTEXT_MGR命令將本身註冊成SMgr時Binder驅動會自動爲它建立Binder實體(這就是那隻預先造好的雞)。其次這個Binder的引用在全部Client中都固定爲0而無須經過其它手段得到。也就是說,一個Server若要向SMgr註冊本身Binder就必需經過0這個引用號和SMgr的Binder通訊。類比網絡通訊,0號引用就比如域名服務器的地址,你必須預先手工或動態配置好。要注意這裏說的Client是相對SMgr而言的,一個應用程序多是個提供服務的Server,但對SMgr來講它仍然是個Client。

3.3 Client 得到實名Binder的引用

Server向SMgr註冊了Binder實體及其名字後,Client就能夠經過名字得到該Binder的引用了。Client也利用保留的0號引用向SMgr請求訪問某個Binder:我申請得到名字叫張三的Binder的引用。SMgr收到這個鏈接請求,從請求數據包裏得到Binder的名字,在查找表裏找到該名字對應的條目,從條目中取出Binder的引用,將該引用做爲回覆發送給發起請求的Client。從面向對象的角度,這個Binder對象如今有了兩個引用:一個位於SMgr中,一個位於發起請求的Client中。若是接下來有更多的Client請求該Binder,系統中就會有更多的引用指向該Binder,就象java裏一個對象存在多個引用同樣。並且相似的這些指向Binder的引用是強類型,從而確保只要有引用Binder實體就不會被釋放掉。經過以上過程能夠看出,SMgr象個火車票代售點,收集了全部火車的車票,能夠經過它購買到乘坐各趟火車的票-獲得某個Binder的引用。

3.4 匿名 Binder

並非全部Binder都須要註冊給SMgr廣而告之的。Server端能夠經過已經創建的Binder鏈接將建立的Binder實體傳給Client,固然這條已經創建的Binder鏈接必須是經過實名Binder實現。因爲這個Binder沒有向SMgr註冊名字,因此是個匿名Binder。Client將會收到這個匿名Binder的引用,經過這個引用向位於Server中的實體發送請求。匿名Binder爲通訊雙方創建一條私密通道,只要Server沒有把匿名Binder發給別的進程,別的進程就沒法經過窮舉或猜想等任何方式得到該Binder的引用,向該Binder發送請求。

相關文章
相關標籤/搜索