Android跨進(jìn)程通信IPC之9——Binder通信機(jī)制

移步系列Android跨進(jìn)程通信IPC系列

1 Android整體架構(gòu)

Android系統(tǒng)架構(gòu)及系統(tǒng)源碼目錄

  • Android系統(tǒng)架構(gòu)分為五層曼月,從上到下依次是應(yīng)用層惠奸、應(yīng)用框架層系統(tǒng)運(yùn)行庫(kù)層蝗茁、硬件抽象層Linux內(nèi)核層
  • 應(yīng)用層:系統(tǒng)內(nèi)置的應(yīng)用程序以及非系統(tǒng)級(jí)的應(yīng)用程序都是屬于應(yīng)用層。
  • 應(yīng)用框架層(Java Framework):應(yīng)用框架層為開(kāi)發(fā)人員提供了可以開(kāi)發(fā)應(yīng)用程序所需要的API都弹,各種Manager(Activity Manager(活動(dòng)管理器),Package Manager(包管理器)匙姜,Telephony Manager(電話管理器)畅厢,View System(視圖系統(tǒng),構(gòu)建應(yīng)用程序的基本組件)氮昧,Content Providers(內(nèi)容提供器))
  • 系統(tǒng)運(yùn)行庫(kù)層(Native):系統(tǒng)運(yùn)行庫(kù)層分為兩部分框杜,分別是C/C++程序庫(kù)和Android運(yùn)行時(shí)庫(kù)浦楣。C/C++程序庫(kù):SQLite數(shù)據(jù)庫(kù),SSL咪辱,OpenGL ES(3D繪圖函數(shù)庫(kù))...振劳。Android運(yùn)行時(shí)庫(kù):ART(5.0系統(tǒng)之后,Dalvik虛擬機(jī)被ART取代)油狂,核心庫(kù)(Java語(yǔ)言核心庫(kù))
  • 硬件抽象層(HAL):其目的在于將硬件抽象化历恐,提供可供"系統(tǒng)服務(wù)層"調(diào)用的統(tǒng)一硬件接口。相機(jī)专筷,藍(lán)牙弱贼,Audio
  • Linux內(nèi)核層:Linux內(nèi)核和各類硬件設(shè)備的驅(qū)動(dòng),這里需要注意的是磷蛹,Binder IPC驅(qū)動(dòng)也是這一層的實(shí)現(xiàn)

每一個(gè)系統(tǒng)服務(wù)在應(yīng)用框架層都有一個(gè)Manager與之對(duì)應(yīng)

5713484-f914d2f622dcf2bc.png

2 IPC原理

從進(jìn)程的角度來(lái)看IPC機(jī)制

5713484-b12db11921797839.png
  • 每個(gè)Android進(jìn)程哮洽,只能運(yùn)行在自己的進(jìn)程所擁有的虛擬地址空間,如果是32位的系統(tǒng)弦聂,對(duì)應(yīng)一個(gè)4GB的虛擬地址空間鸟辅,其中3GB是用戶空,1GB是內(nèi)核空間莺葫,而內(nèi)核空間的大小是可以通過(guò)參數(shù)配置的匪凉。
  • 對(duì)于用戶空間,不同進(jìn)程之間彼此是不能共享的捺檬,而內(nèi)核空間確實(shí)可以共享的再层。
  • Client進(jìn)程與Server進(jìn)程通信,恰恰是利用進(jìn)程間可共享的內(nèi)核內(nèi)空間來(lái)完成底層通信工作的堡纬,Client端與Server端進(jìn)程往往采用ioctl等方法跟內(nèi)核空間的驅(qū)動(dòng)進(jìn)行聂受。

3 Binder綜述

3.1 Binder簡(jiǎn)介

3.1.1 Binder的由來(lái)

  • Binder是Android平臺(tái)上的一種跨進(jìn)程通信技術(shù)。
  • 最早并不是谷歌公司提出的烤镐,它前身是Be Inc公司開(kāi)發(fā)的OpenBinder蛋济,而且在Palm中也有應(yīng)用
  • 后來(lái)OpenBinder的作者Dianne Hackborn加入了谷歌公司,并負(fù)責(zé)Android平臺(tái)開(kāi)發(fā)的工作炮叶,所以把這項(xiàng)技術(shù)也帶進(jìn)了Android碗旅。

3.1.2 什么是Binder

    1. 從來(lái)類的角度來(lái)說(shuō),Binder就是Android的一個(gè)類镜悉,它繼承了IBinder接口
    1. 從IPC的角度來(lái)說(shuō)祟辟,Binder是Android中的一個(gè)中的一種跨進(jìn)程通信方式,Binder還可以理解為一種虛擬的物理設(shè)備侣肄,它的設(shè)備驅(qū)動(dòng)是/dev/binder旧困,該通信方式在Linux中沒(méi)有(由于耦合性太強(qiáng),而Linux沒(méi)有接納)
    1. 從Android Framework角度來(lái)說(shuō),Binder是ServiceManager連接各種Manager(ActivityManager吼具、WindowManager等)和相應(yīng)的ManagerService的橋梁
  • 4 從Android應(yīng)用層的角度來(lái)說(shuō)被芳,Binder是客戶端和服務(wù)端進(jìn)行通信的媒介,當(dāng)你bindService的時(shí)候馍悟,服務(wù)端會(huì)返回一個(gè)包含了服務(wù)端業(yè)務(wù)調(diào)用的Binder對(duì)象畔濒,通過(guò)這個(gè)Binder對(duì)象,客戶端就可以獲取服務(wù)端提供的服務(wù)或者數(shù)據(jù)锣咒,這里的服務(wù)包括普通服務(wù)和基于AIDL的服務(wù)侵状。

3.1.3 Binder機(jī)制的意義

  • Binder機(jī)制具有兩層含義:
  • 1 是一種跨進(jìn)程通信的方式(IPC)
  • 2 是一種遠(yuǎn)程過(guò)程調(diào)用方式(PRC)

而從實(shí)現(xiàn)的角度來(lái)說(shuō),Binder核心被實(shí)現(xiàn)成一個(gè)Linux驅(qū)動(dòng)程序毅整,并運(yùn)行于內(nèi)核態(tài)趣兄。這樣它才能具有強(qiáng)大的跨進(jìn)程訪問(wèn)能力。

3.1.4 和傳統(tǒng)IPC機(jī)制相比悼嫉,谷歌為什么采用Binder

  • 雖然Android繼承Linux內(nèi)核艇潭,但是Linux與Android通信機(jī)制是不同的。
  • Android中有大量的C/S(Client/Server)應(yīng)用方式戏蔑,這就要求Android內(nèi)部提供IPC方法蹋凝,而如果采用Linux所支持的進(jìn)程通信方式有兩個(gè)問(wèn)題:性能安全性
    Android跨進(jìn)程通信IPC系列
  • 性能:目前Linux支持的IPC包括傳統(tǒng)的管道总棵,System V IPC(包括消息隊(duì)列/共享內(nèi)存/信號(hào)量)以及socket鳍寂,但是只有socket支持Client/Server的通信方式,由于socket是一套通用當(dāng)初網(wǎng)絡(luò)通信方式情龄,其效率低下迄汛,且消耗比較大(socket建立連接過(guò)程和中斷連接過(guò)程都有一定的開(kāi)銷(xiāo)),明顯在手機(jī)上不適合大面積使用socket骤视。而消息隊(duì)列和管道采用"存儲(chǔ)-轉(zhuǎn)發(fā)" 方式鞍爱,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開(kāi)辟的緩存區(qū)中,然后再?gòu)膬?nèi)核緩存中拷貝到接收方緩存中专酗,至少有兩次拷貝過(guò)程睹逃。共享內(nèi)存雖然無(wú)需拷貝,但控制復(fù)雜笼裳,難以使用唯卖。
  • 安全性:在安全性方面粱玲,Android作為一個(gè)開(kāi)放式躬柬,擁有眾多開(kāi)發(fā)者的平臺(tái),應(yīng)用程序的來(lái)源廣泛抽减,確保智能終端的安全是非常重要的允青。終端用戶不希望從網(wǎng)上下載的程序在不知情的情況下偷窺隱私數(shù)據(jù),連接無(wú)線網(wǎng)絡(luò)卵沉,長(zhǎng)期操作底層設(shè)備導(dǎo)致電池很快耗盡的情況颠锉。傳統(tǒng)IPC沒(méi)有任何安全措施法牲,完全依賴上層協(xié)議來(lái)去報(bào)。首先傳統(tǒng)IPC的接受方無(wú)法獲取對(duì)方進(jìn)程可靠的UID/PID(用戶ID/進(jìn)程ID)琼掠,從而無(wú)法鑒別對(duì)方身份拒垃。Android為每個(gè)安裝好的應(yīng)用程序分配了自己的UID,故進(jìn)程的UID是鑒別進(jìn)程的身份的重要標(biāo)志瓷蛙。使用傳統(tǒng)IPC只能由用戶在數(shù)據(jù)包里填入U(xiǎn)ID/PID悼瓮,但這樣不可靠,容易被惡意程序利用艰猬『岜ぃ可靠的身份標(biāo)記只由IPC機(jī)制本身在內(nèi)核中添加其次傳統(tǒng)IPC訪問(wèn)接入點(diǎn)是開(kāi)放的冠桃,無(wú)法建立私有通道命贴。比如命名管道、system V的鍵值食听,socket的ip地址或者文件名都是開(kāi)放的胸蛛,只要知道這些接入點(diǎn)的程序都可以對(duì)端建立連接,不管怎樣都無(wú)法阻止惡意程序通過(guò)接收方地址獲得連接樱报。
  • 基于以上原因胚泌,Android需要建立一套新的IPC機(jī)制來(lái)滿足系統(tǒng)對(duì)通信方式傳輸性能安全性的要求肃弟,所以就有了Binder玷室。

  • Binder基于Client/Server通信模式,傳輸過(guò)程只需要一次拷貝笤受,為發(fā)送發(fā)添加UID/PID身份穷缤,即支持實(shí)名Binder也支持匿名Binder,安全性高箩兽。

  • Binder通信過(guò)程示例


    5713484-235dbffbd3b4e3fa.png
  • 通信雙方必須要處理線程同步津肛,內(nèi)存管理等問(wèn)題,工作量大汗贫,而且問(wèn)題多身坐,

  • 介紹的傳統(tǒng)IPC 命名管道(FIFO) 信號(hào)量(semaphore) 消息隊(duì)列已經(jīng)從Android中去掉了,同其他IPC相比落包,Socket是一種比較成熟的通信手段了部蛇,同步控制也很容易實(shí)現(xiàn)。Socket用于網(wǎng)絡(luò)通信非常合適咐蝇,但是用于進(jìn)程間通信就效率很低涯鲁。

  • Android在架構(gòu)上一直希望模糊進(jìn)程的概念,取而代之以組件的概念。應(yīng)用也不需要關(guān)心組件存放的位置抹腿、組件運(yùn)行在那個(gè)進(jìn)程中岛请、組件的生命周期等問(wèn)題。隨時(shí)隨地的警绩,只要擁有Binder對(duì)象崇败,就能使用組件的功能。Binder就像一張網(wǎng)肩祥,將整個(gè)系統(tǒng)的組件僚匆,跨進(jìn)程和線程的組織在一起

  • Binder是整個(gè)系統(tǒng)的運(yùn)行的中樞搭幻。Android在進(jìn)程間傳遞數(shù)據(jù)使用共享內(nèi)存的方式咧擂,這樣數(shù)據(jù)只需要復(fù)制一次就能從一個(gè)進(jìn)程到達(dá)另一個(gè)進(jìn)程了(前面文章說(shuō)了,一般IPC都需要兩步檀蹋,第一步用戶進(jìn)程復(fù)制到內(nèi)核松申,第二步再?gòu)膬?nèi)核復(fù)制到服務(wù)進(jìn)程。)

  • PS: 整個(gè)Androdi系統(tǒng)架構(gòu)中俯逾,雖然大量采用了Binder機(jī)制作為IPC(進(jìn)程間通信)方式贸桶,但是也存在部分其他的IPC方式,比如Zygote通信就是采用socket桌肴。

3.1.5 Binder在Service服務(wù)中的作用

在Android中皇筛,有很多Service都是通過(guò)Binder來(lái)通信的,比如MediaService名下的眾多Service:

  • AudioFlinger音頻核心服務(wù)
  • AudioPolicyService:音頻策略相關(guān)的重要服務(wù)
  • MediaPlayerService:多媒體系統(tǒng)中的重要服務(wù)
  • CarmeraService:有關(guān)攝像/照相的重要服務(wù)

3.2 總結(jié)

  • Android Binder 是在OpenBinder上定制實(shí)現(xiàn)的坠七。原先的OpenBinder 框架現(xiàn)在已經(jīng)不再繼續(xù)開(kāi)發(fā)水醋,所以也可以說(shuō)Android讓原先的OpenBinder得到了重生。Binder是Android上大量使用的IPC(Inter-process communication彪置,進(jìn)程間通訊)機(jī)制拄踪。
  • 無(wú)論是應(yīng)用程序?qū)ο到y(tǒng)服務(wù)的請(qǐng)求,還是應(yīng)用程序自身提供對(duì)外服務(wù)拳魁,都需要使用Binder惶桐。

整體架構(gòu)

5713484-b6d551adc5cd602c.png

從圖中可以看出,Binder的實(shí)現(xiàn)分為這幾層潘懊,按照大的框架理解是

  • framewor層
    --- ---java 層
    --- ---jni 層
    --- ---native/ C++層
  • linux驅(qū)動(dòng)層 c語(yǔ)言
  • 其中Linux驅(qū)動(dòng)層位于Linux內(nèi)核中姚糊,它提供了最底層的數(shù)據(jù)傳遞,對(duì)象標(biāo)示授舟,線程管理救恨,通過(guò)調(diào)用過(guò)程控制等功能。驅(qū)動(dòng)層其實(shí)是Binder機(jī)制的核心岂却。

  • Framework層以Linux驅(qū)動(dòng)層為基礎(chǔ)忿薇,提供了應(yīng)用開(kāi)發(fā)的基礎(chǔ)設(shè)施裙椭。Framework層既包含了C++部分的實(shí)現(xiàn)躏哩,也包含了Java基礎(chǔ)部分的實(shí)現(xiàn)署浩。為了能將C++ 的實(shí)現(xiàn)復(fù)用到Java端,中間通過(guò)JNI進(jìn)行銜接扫尺。

  • Binder框架是典型的C/S架構(gòu)筋栋。

  • 我們把服務(wù)的請(qǐng)求方稱為Client,服務(wù)的實(shí)現(xiàn)方稱之Server正驻。Clinet對(duì)于Server的請(qǐng)求會(huì)經(jīng)由Binder驅(qū)動(dòng)框架由上至下傳遞到內(nèi)核的Binder驅(qū)動(dòng)中弊攘,請(qǐng)求中包含了Client將要調(diào)用的命令和參數(shù)。

  • 請(qǐng)求到了Binder驅(qū)動(dòng)以后姑曙,在確定了服務(wù)的提供方之后襟交,再講從下至上將請(qǐng)求傳遞給具體的服務(wù)。

5713484-61c89cf6753c0f2a.png

4 Binder通信機(jī)制

Android內(nèi)部采用C/S架構(gòu)伤靠。而B(niǎo)inder通信也是采用C/S架構(gòu)捣域。那我們來(lái)看下Binder在C/S的中的流程。

4.1 Binder在C/S中的流程

5713484-27da6c30d6c832af.png

具體流程如下:

    1. 相應(yīng)的Service需要注冊(cè)服務(wù)宴合。Service作為很多Service的擁有者焕梅,當(dāng)它想向Client提供服務(wù)時(shí),得先去Service Manager(以后縮寫(xiě)成SM)那兒注冊(cè)自己的服務(wù)卦洽。Server可以向SM注冊(cè)一個(gè)或者多個(gè)服務(wù)贞言。
    1. Client申請(qǐng)服務(wù)。Client作為Service的使用者阀蒂,當(dāng)他想使用服務(wù)時(shí)该窗,得向SM申請(qǐng)自己所需要的服務(wù)。Client可以申請(qǐng)一個(gè)或者多個(gè)服務(wù)蚤霞。
    1. 當(dāng)Client申請(qǐng)服務(wù)成功后挪捕,Client就可以使用服務(wù)了。
  • SM一方面管理Server所提供的服務(wù)争便,同時(shí)又響應(yīng)Client的請(qǐng)求并為之分配響應(yīng)的服務(wù)级零。
  • 通信方式的好處是:
  • 一方面,service和Client請(qǐng)求便于管理
  • 另一方面在應(yīng)用程序開(kāi)發(fā)時(shí)滞乙,只需要為Client建立到Server的連接即可奏纪,這樣只需要花很少的時(shí)間成本去實(shí)現(xiàn)Server的相應(yīng)功能。
  • 那么Binder與這個(gè)通信有什么關(guān)系斩启?其實(shí)三者的通信方式就是Binder機(jī)制(比如Server向SM注冊(cè)服務(wù)序调,使用Binder通信;Client申請(qǐng)請(qǐng)求也是Binder通信兔簇。)

PS:注意這里的ServiceManager是指Nativie層的ServiceManager(C++)发绢,并非是framework層的ServiceManager(Java)硬耍。ServiceManager是整個(gè)Binder通信機(jī)制的大管家,是Android進(jìn)程間通信機(jī)制的守護(hù)進(jìn)程边酒。

4.2 Binder通信整體框架

后面我們會(huì)不斷的提及兩個(gè)概念经柴,一個(gè)是Server,還有一個(gè)是Service墩朦,我這里先強(qiáng)調(diào)下坯认,Server是Server,Service是Service氓涣,大家不要混淆牛哺,一個(gè)Server下面可能有很多Service,但是一個(gè)Servcie也只能隸屬于一個(gè)Server劳吠。

4.2.1 從內(nèi)核和用戶空間的角度來(lái)看

Binder通信模型如下:


5713484-a2f22475b603fe44.png

我們可以發(fā)現(xiàn):

    1. Client和Server是存在于用戶空間
    1. Client和Server通信實(shí)現(xiàn)是由Binder驅(qū)動(dòng)在內(nèi)核的實(shí)現(xiàn)
    1. SM作為守護(hù)進(jìn)程引润,處理客戶端請(qǐng)求,管理所有服務(wù)

我們可以把SM理解成為DNS服務(wù)器痒玩,那么Binder Driver就相當(dāng)于路由的功能淳附。

4.2.2 從Android的層級(jí)的角度

如下圖:(注意圖片的右邊)


5713484-a967860ae78d6e7b.png
  • Client/Server/ServiceManager之間的相互通信都是基于Binder機(jī)制。
  • Clinet/Server/ServiceManager之間交互都是虛線表示凰荚,是由于他們彼此之間不直接交互燃观,都是通過(guò)Binder驅(qū)動(dòng)進(jìn)行交互,從而實(shí)現(xiàn)IPC通信方式便瑟。
  • 其中Binder驅(qū)動(dòng)位于內(nèi)核空間缆毁,Client/Server/ServiceManager可以看做是Android平臺(tái)的基礎(chǔ)架構(gòu)。
  • Client和Server是Android的應(yīng)用層到涂,開(kāi)發(fā)人員只需要自定義實(shí)現(xiàn)client脊框、Server端,借助Android的基本平臺(tái)架構(gòu)就可以直接進(jìn)行IPC通信践啄。

4.2.3 從Binder的架構(gòu)角度來(lái)看

5713484-8beb526a979a9fbb.png
  • Binder IPC 屬于 C/S 結(jié)構(gòu)浇雹,Client 部分是用戶代碼,用戶代碼最終會(huì)調(diào)用 Binder Driver 的 transact 接口屿讽,Binder Driver 會(huì)調(diào)用 Server昭灵,這里的 Server 與 service 不同,可以理解為 Service 中 onBind 返回的 Binder 對(duì)象伐谈,請(qǐng)注意區(qū)分下烂完。
  • Client端:用戶需要實(shí)現(xiàn)的代碼,如 AIDL 自動(dòng)生成的接口類
  • Binder Driver:在內(nèi)核層實(shí)現(xiàn)的 Driver
  • Server端:這個(gè) Server 就是 Service 中 onBind 返回的 IBinder 對(duì)象
  • 上面綠色的色塊部分都是屬于用戶需要實(shí)現(xiàn)的部分诵棵,而藍(lán)色部分是系統(tǒng)去實(shí)現(xiàn)了抠蚣。
  • Binder Driver 這塊并不需要知道,Server 中會(huì)開(kāi)啟一個(gè)線程池去處理客戶端調(diào)用履澳。
  • 為什么要用線程池而不是一個(gè)單線程隊(duì)列呢嘶窄?試想一下怀跛,如果用單線程隊(duì)列,則會(huì)有任務(wù)積壓柄冲,多個(gè)客戶端同時(shí)調(diào)用一個(gè)服務(wù)的時(shí)候就會(huì)有來(lái)不及響應(yīng)的情況發(fā)生吻谋,這是絕對(duì)不允許的。
  • 對(duì)于調(diào)用 Binder Driver 中的 transact 接口羊初,客戶端可以手動(dòng)調(diào)用滨溉,也可以通過(guò) AIDL 的方式生成的代理類來(lái)調(diào)用
  • 服務(wù)端可以繼承 Binder 對(duì)象什湘,也可以繼承 AIDL 生成的接口類的** Stub 對(duì)象**长赞。

切記,這里 Server 的實(shí)現(xiàn)是線程池的方式闽撤,而不是單線程隊(duì)列的方式得哆,區(qū)別在于,單線程隊(duì)列的話哟旗,Server 的代碼是線程安全的贩据,線程池的話,Server 的代碼則不是線程安全的闸餐,需要開(kāi)發(fā)者自己做好多線程同步饱亮。

4.3 Binder流程

4.3.1 Server向SM注冊(cè)服務(wù)

5713484-4b933c042f2712d7.png
    1. 首先 XXServer(XXX代表某個(gè))在自己的進(jìn)程中向Binder驅(qū)動(dòng)申請(qǐng)創(chuàng)建一個(gè)XXXService的Binder實(shí)體。
    1. Binder驅(qū)動(dòng)為這個(gè)XXXService創(chuàng)建位于內(nèi)核中的Binder實(shí)體節(jié)點(diǎn)以及Binder的引用包颁,注意饵隙,是將名字和新建的引用打包傳遞給SM(實(shí)體沒(méi)有傳給SM)阀捅,通知SM注冊(cè)一個(gè)名叫XXX的Service。
    1. SM收到數(shù)據(jù)包后壹无,從中取出XXXService名字和引用,填入一張查找表中
  • 4感帅、此時(shí)斗锭,如果有Client向SM發(fā)送申請(qǐng)服務(wù)XXXService的請(qǐng)求,那么SM就可以查找表中該Service的Binder引用失球,并把BInder引用(XXXBpBinder返回給Client)

在進(jìn)一步了解Binder通信機(jī)制之前岖是,我們先弄清楚幾個(gè)概念。

  • 引用和實(shí)體实苞。這里豺撑,對(duì)于一個(gè)用于通信的實(shí)體(可以理解為真實(shí)空間的Object),可以額有多個(gè)該實(shí)體的引用(沒(méi)有真實(shí)空間硬梁,可以理解成實(shí)體的一個(gè)鏈接前硫,操作引用就可以操作對(duì)應(yīng)鏈接上的實(shí)體)。如果一個(gè)進(jìn)程持有某個(gè)實(shí)體荧止,其他進(jìn)程也想操作該實(shí)體屹电,最高效的做法是去獲取該實(shí)體的引用阶剑,再去操作這個(gè)引用。

為了大家在后面更好的理解危号,這里補(bǔ)充幾個(gè)概念

  • Binder實(shí)體對(duì)象 :Binder實(shí)體對(duì)象就是Binder服務(wù)的提供者牧愁。一個(gè)提供Binder服務(wù)的類必須繼承BBinder類,因此外莲,有時(shí)為了強(qiáng)調(diào)對(duì)象類型猪半,也用"BBinder對(duì)象"來(lái)代替"Binder實(shí)體對(duì)象"。
  • Binder引用對(duì)象 :Binder引用對(duì)象是Binder實(shí)體對(duì)象在客戶進(jìn)程的代表偷线,每個(gè)引用對(duì)象的類型都是BpBiner類磨确,同樣可以用名稱"BpBinder對(duì)象"來(lái)代替"Binder引用對(duì)象"。
  • Binder代理對(duì)象 :代理對(duì)象也成為接口對(duì)象声邦,它主要是為了客戶端的上層應(yīng)用提供接口服務(wù)乏奥,從IInterface類派生。它實(shí)現(xiàn)了Binder服務(wù)的函數(shù)接口亥曹,當(dāng)然只是一個(gè)轉(zhuǎn)調(diào)的空殼邓了。通過(guò)代理對(duì)象,應(yīng)用能像使用本地對(duì)象一樣使用遠(yuǎn)端實(shí)體對(duì)象提供服務(wù)媳瞪,將Binder代理對(duì)象和Binder引用對(duì)應(yīng)(BpBinder對(duì)象)分開(kāi)的好處是代理對(duì)象可以有很多實(shí)例骗炉,但是它們包含的是同一個(gè)引用對(duì)象,這樣方便了應(yīng)用層的使用蛇受。句葵。
  • IBiner對(duì)象 :BBinder和BpBinder類是從IBinder類中繼承來(lái)。在很多場(chǎng)合龙巨,不需要刻意地去區(qū)分實(shí)體對(duì)象和引用對(duì)象笼呆,這時(shí)候也可以統(tǒng)一使用"IBinder對(duì)象"來(lái)統(tǒng)一稱呼他們。
5713484-16da386aeb274c42.png
  • 這樣應(yīng)用層可以直接拋開(kāi)接口對(duì)象直接使用Binder的引用對(duì)象旨别,但是這樣開(kāi)發(fā)的程序兼容性不好诗赌。也正是客戶端將引用對(duì)象和代理對(duì)象分離,Android才能用一套架構(gòu)來(lái)同時(shí)為Java和native層提供Binder服務(wù)秸弛。隔離后铭若,Binder底層不需要關(guān)系上層的實(shí)現(xiàn)細(xì)節(jié),只需要和Binder實(shí)體對(duì)象和引用對(duì)象進(jìn)行交互递览。

PS:BpBinder(Binder引用對(duì)象,在客戶端)和BBinder(Binder實(shí)體,在服務(wù)端)都是Android中Binder通信相關(guān)的代表叼屠,它們都是從IBiner類中派生而來(lái)(BpBinder和BBinder在Native層,不在framework層)绞铃,

5713484-f7abd498f0cec6b6.png

client端:BpBinder通過(guò)調(diào)用transact()來(lái)發(fā)送事物請(qǐng)求
server端:BBinder通過(guò)onTransact()會(huì)接受到相應(yīng)的事物

這時(shí)候再來(lái)看下這個(gè)圖镜雨,然后大家思考一下,就會(huì)明白很多事情儿捧。


5713484-e7b48b84550c62a2.png

4.3.2 如何獲得一個(gè)SM的遠(yuǎn)程接口

5713484-421f20db093018e9.png

如果你足夠細(xì)心荚坞,你會(huì)發(fā)現(xiàn)這里有一個(gè)問(wèn)題:

SM和Server都是進(jìn)程挑宠,Server向SM注冊(cè)Binder需要進(jìn)程間通信,當(dāng)前實(shí)現(xiàn)的是進(jìn)程間通信颓影,卻又用到進(jìn)程間通信各淀。有點(diǎn)暈是不,就好像先有雞還是先有蛋這個(gè)問(wèn)題诡挂。

其實(shí)Binder是這么解決這個(gè)問(wèn)題的:

  • 針對(duì)Binder的通信機(jī)制碎浇,Server端擁有的是Binder的實(shí)體(BBinder);Client擁有的是Binder的引用(BpBinder)璃俗。
  • 如果把SM看做Server端奴璃,讓它在Binder驅(qū)動(dòng)一起運(yùn)行起來(lái)時(shí)就有自己的實(shí)體(BBinder)(代碼中設(shè)置ServiceManager的Binder其handle的值恒為0)。這個(gè)Binder實(shí)體沒(méi)有名字也不需要注冊(cè)旧找,所有的Client都認(rèn)為handle值為0的binder引用(BpBinder)是用來(lái)與SM通信的溺健。那么這個(gè)問(wèn)題就解決了麦牺。
  • Client和Server中handle的值為0(值為0的引用是專門(mén)與SM通信用的)钮蛛,還不行,還需要讓SM的handle值為0的實(shí)體(BBinder)為0才算大功告成剖膳。怎么實(shí)現(xiàn)的? 當(dāng)一個(gè)進(jìn)程調(diào)用Binder驅(qū)動(dòng)時(shí)魏颓,使用** "BINDER_SET_CONTEXXT_MGR" ** 命名(在binder_ioctl中)將自己注冊(cè)成SM時(shí),Binder驅(qū)動(dòng)會(huì)自動(dòng)為她創(chuàng)建Binder實(shí)體吱晒。這個(gè)Binder的引用對(duì)所有Client都為0甸饱。

4.3.3 Client從SM中獲得Service的遠(yuǎn)程接口

  • Server向SM注冊(cè)了Binder實(shí)體及其名字后,Client就可以Service的名字在SM在查找表中獲得了該Binder的引用(BpBinder)了
  • Client也利用了保留的handle值為0的引用向SM請(qǐng)求訪問(wèn)某個(gè)Service:當(dāng)申請(qǐng)?jiān)L問(wèn)XXXService的引用仑濒。
  • SM就會(huì)從請(qǐng)求數(shù)據(jù)包中獲得XXXService的名字叹话,在查找表中找到名字對(duì)應(yīng)的條目,取出Binder的引用打包回復(fù)給Client墩瞳。
  • Client就可以利用XXXService的引用使用XXXService的服務(wù)了驼壶。如果有更多的Client請(qǐng)求該Service,系統(tǒng)中就會(huì)有更多的Client獲得這個(gè)引用喉酌。

如下圖

5713484-306663b15530322c.png

4.3.4 建立C/S連接后

首先要明白一個(gè)事情:

Client要擁有自己的自己的Binder實(shí)體热凹,以及Server的Binder的應(yīng)用;Server有用自己的Binder的實(shí)體泪电,以及Client的Binder引用般妙。

我們也可以按照網(wǎng)絡(luò)請(qǐng)求的方式來(lái)分析:

  • 從Client向Server發(fā)送數(shù)據(jù):Client為發(fā)送方,擁有Binder實(shí)體相速;Server為接收方碟渺,擁有Binder引用。
  • 從Server向Client發(fā)送數(shù)據(jù):Server為發(fā)送方突诬,擁有Binder實(shí)體:Client為接收方苫拍,擁有Binder引用烹棉。

其實(shí),在我們建立C/S連接后怯疤,無(wú)需考慮誰(shuí)是Client浆洗,誰(shuí)是Server。只要理清誰(shuí)是發(fā)送方集峦,誰(shuí)是接收方伏社,就能知道Binder的實(shí)體和應(yīng)用在那邊。

那我們看下建立C/S連接后的塔淤,具體流程,如下圖:


5713484-4c7fcd2e70d997c0.png

那我們說(shuō)下具體的流程:

  • 第一步摘昌,發(fā)送方通過(guò)Binder實(shí)體請(qǐng)求發(fā)送操作
  • 第二步,Binder驅(qū)動(dòng)會(huì)處理這個(gè)操作請(qǐng)求高蜂,把發(fā)送方的數(shù)據(jù)放入寫(xiě)緩存(binder_write_read.write_buffer)(對(duì)于接受方來(lái)說(shuō)為讀緩存區(qū))聪黎,并把read_size(接收方讀數(shù)據(jù))置為數(shù)據(jù)大小。
  • 第三步备恤,接收方之前一直在阻塞狀態(tài)中稿饰,當(dāng)寫(xiě)緩存有數(shù)據(jù),則會(huì)讀取數(shù)據(jù)露泊,執(zhí)行命令操作
  • 第四步喉镰,接收方執(zhí)行完后,會(huì)把返回結(jié)果同樣采用binder_transaction_data結(jié)構(gòu)體封裝惭笑,寫(xiě)入緩沖區(qū)(對(duì)于發(fā)送方侣姆,為讀緩沖區(qū))

4.3.4 匿名Binder

  • 在Android中Binder還可以建立點(diǎn)對(duì)點(diǎn)的私有通道,匿名Binder就是這種方式沉噩。
  • 在Binder通信中捺宗,并不是所有通信的Binder實(shí)體都需要注冊(cè)給SM的,Server可以通過(guò)已建立的實(shí)體Binder連接將創(chuàng)建的Binder實(shí)體傳給Client川蒙。
  • 這個(gè)Binder沒(méi)有向SM注冊(cè)名字蚜厉。這樣Server和Client通信就有很高的隱私性和安全性。

如下圖:


5713484-32f314f85b38a4f3.png

5 Binder的層次

從代碼上看派歌,Binder設(shè)計(jì)的類可以分成4個(gè)層級(jí)弯囊,如下圖所示


5713484-c4e04f1f98aad092.png
  • 最上層的是位于Framewok中的各種Binder服務(wù)類和它們的接口類。這一層的類非常多胶果,比如常見(jiàn)的ActivityManagerService(縮寫(xiě)叫AMS)匾嘱、WindowManagerService(縮寫(xiě)叫WMS)、PackageManagerService(縮寫(xiě)是PMS)等早抠,它們?yōu)閼?yīng)用程序提供了各種各樣的服務(wù)霎烙。
  • 中間則分為為兩層,上面是用于服務(wù)類和接口開(kāi)發(fā)的基礎(chǔ),比如IBinder悬垃、BBinder游昼、BpBinder等。下層是和驅(qū)動(dòng)交互的IPCThreadState和ProcessState類尝蠕。
  • 這里刻意把中間的libbinder中的類劃分為兩個(gè)層次的原因烘豌,是在這4層中,第一層的和第二層聯(lián)系很緊密看彼,第二層中的 各種Binder類用來(lái)支撐服務(wù)類和代理類的開(kāi)發(fā)廊佩。但是第三層的IPCThread和第四層之間耦合得很厲害,單獨(dú)理解IPCThread或者是驅(qū)動(dòng)都是一件很難的事靖榕,必須把它們結(jié)合起來(lái)理解标锄,這一點(diǎn)正是Binder架構(gòu)被人詬病的地方,驅(qū)動(dòng)和應(yīng)用層之間過(guò)于耦合茁计,違反了Linux驅(qū)動(dòng)設(shè)計(jì)的原則料皇,因此,主流的Linux并不愿意接納Binder

6 Binder協(xié)議

Biner協(xié)議格式基本是"命令+數(shù)據(jù)"星压,使用ioctl(fd,cmd,arg)函數(shù)實(shí)現(xiàn)交互践剂。命令由參數(shù)cmd承載數(shù)據(jù)由參數(shù)arg租幕,隨著cmd不同而不動(dòng)舷手。

命令 含義 參數(shù)(arg)
BINDER_WRITE_READ 該命令向Binder寫(xiě)入或讀取數(shù)據(jù)。參數(shù)分為兩段:寫(xiě)部分和讀部分劲绪。如果write_size不為0,就將write_buffer里的數(shù)據(jù)寫(xiě)入Binder盆赤;如果read_ size不為0再?gòu)腂inder中讀取數(shù)據(jù)存入read_buffer中贾富。write_consumered和read_consumered表示操作完成時(shí)Binder驅(qū)動(dòng)實(shí)際寫(xiě)入或者讀出數(shù)據(jù)的個(gè)數(shù) struct binder_write_read{ singed long write_size;singed long write_consumed; unsigned long write_buffer; signed long read_size; signed long read_consumed; unsigned long read_buffer; } ;
BINDER_SET_MAX_THREADS 該命令告知Binder驅(qū)動(dòng)接收方(通常是Server端)線程池中最大的線程數(shù)。由于Client是并發(fā)向Server端發(fā)送請(qǐng)求的牺六,Server端必須開(kāi)辟線程池為這些并發(fā)請(qǐng)求提供服務(wù) 颤枪。告知驅(qū)動(dòng)線程池的最大值是為了讓驅(qū)動(dòng)發(fā)現(xiàn)線程數(shù)達(dá)到該線程池的最大值是為了讓驅(qū)動(dòng)發(fā)現(xiàn)線程數(shù)達(dá)到該值時(shí),不要再命令接收端啟動(dòng)先的線程淑际。 int max_threads;
BINDER_SET_CONTEXT_MGR 當(dāng)前進(jìn)程注冊(cè)為SM畏纲。系統(tǒng)中只能存在一個(gè)SM,只要當(dāng)前的SM沒(méi)有調(diào)用close()關(guān)閉春缕,Binder驅(qū)動(dòng)就不能有別的進(jìn)程變成SM 無(wú)
BINDER_TREAD_EXIT 通知Binder驅(qū)動(dòng)當(dāng)前線程退出了盗胀。Binder會(huì)為所有參與的通信線程(包括Server線程池中的線程和Client發(fā)出的請(qǐng)求的線程) 建立相應(yīng)的數(shù)據(jù)結(jié)構(gòu)。這些線程在退出時(shí)必須通知驅(qū)動(dòng)釋放相應(yīng)的數(shù)據(jù)結(jié)構(gòu) 無(wú)
BINDER_VERSION 獲取Binder驅(qū)動(dòng)的版本號(hào) 無(wú)

這其中最常用的命令是 BINDER_WRITE_READ锄贼。該命令的參數(shù)包括兩個(gè)部分:

    1. 是向Binder寫(xiě)入數(shù)據(jù)
    1. 是向Binder讀出數(shù)據(jù)
  • 驅(qū)動(dòng)程序先處理寫(xiě)部分再處理讀部分票灰。這樣安排的好處是應(yīng)用程序可以很靈活的地處理命令的同步或者異步。

  • 例如若要發(fā)送異步命令可以只填入寫(xiě)部分而將read_size設(shè)置為0,若要只從Binder獲得的數(shù)據(jù)可以將寫(xiě)部分置空屑迂,即write_size置0浸策。如果想要發(fā)送請(qǐng)求并同步等待返回?cái)?shù)據(jù)可以將兩部分都置上

6.1 BINDER_WRITE_READ 之寫(xiě)操作

  • Binder寫(xiě)操作的數(shù)據(jù)時(shí)格式同樣也是(命令+數(shù)據(jù))惹盼。這時(shí)候命令和數(shù)據(jù)都存放在binder_write_read結(jié)構(gòu)中的write_buffer域指向的內(nèi)存空間里庸汗,多條命令可以連續(xù)存放
  • 數(shù)據(jù)緊接著存放在命令后面手报,格式根據(jù)命令不同而不同夫晌。下表列舉了Binder寫(xiě)操作支持的命令:
  • 我提供兩套,一套是圖片昧诱,方便手機(jī)用戶晓淀,一部分是文字,方便PC用戶


    5713484-ffb7c05eaa6f6eaa.png

上面圖片盏档,下面是文字

命令 含義 參數(shù)(arg)
BC_TRANSACTION BC_REPLY BC_TRANSACTION用于Client向Server發(fā)送請(qǐng)求數(shù)據(jù)凶掰;BC_REPLY用于Server向Client發(fā)送回復(fù)(應(yīng)答)數(shù)據(jù)。其后面緊接著一個(gè)binder_transaction_data結(jié)構(gòu)體表明要寫(xiě)入的數(shù)據(jù)蜈亩。 struct binder_transaction_data
BC_ACQUIRE_RESULT 暫未實(shí)現(xiàn)
BC_FREE_BUFFER 釋放一塊映射內(nèi)存懦窘。Binder接受方通過(guò)mmap()映射一塊較大的內(nèi)存空間,Binder驅(qū)動(dòng)基于這片內(nèi)存采用最佳匹配算法實(shí)現(xiàn)接受數(shù)據(jù)緩存的動(dòng)態(tài)分配和釋放稚配,滿足并發(fā)請(qǐng)求對(duì)接受緩存區(qū)的需求畅涂。應(yīng)用程序處理完這篇數(shù)據(jù)后必須盡快使用費(fèi)改命令釋放緩存區(qū),否則會(huì)因?yàn)榫彺鎱^(qū)耗盡而無(wú)法接受新數(shù)據(jù) 指向需要釋放的緩存區(qū)的指針道川;該指針位于收到的Binder數(shù)據(jù)包中
BC_INCREFS BC_ACQUIRE BC_RELEASE BC_DECREFS 這組命令增加或減少Binder的引用計(jì)數(shù)午衰,用以實(shí)現(xiàn)強(qiáng)指針或弱指針的功能 32位Binder引用號(hào)
BC_REGISTER_LOOPER BC_ENTER_LOOPER BC_EXIT_LOOPER 這組命令同BINDER_SET_MAX_THREADS 一并實(shí)現(xiàn)Binder驅(qū)動(dòng)對(duì)接收方線程池的管理。BC_REGISTER_LOOPER通知驅(qū)動(dòng)線程池中的一個(gè)線程已經(jīng)創(chuàng)建了冒萄;BC_ENTER_LOOPER通知該驅(qū)動(dòng)線程已經(jīng)進(jìn)入主循環(huán)臊岸,可以接受數(shù)據(jù);BC_EXIT_LOOPER通知驅(qū)動(dòng)該線程退出主循環(huán)尊流,不在接受數(shù)據(jù)帅戒。 -----
BC_REQUEST_DEATH_NOTIFICATION 獲得Binder引用的進(jìn)程通過(guò)該命令要求驅(qū)動(dòng)在Binder實(shí)體銷(xiāo)毀得到通知。雖說(shuō)強(qiáng)指針可以確保只要有引用就不會(huì)銷(xiāo)毀實(shí)體崖技,但這畢竟是個(gè)跨進(jìn)程的引用逻住,誰(shuí)也無(wú)法保證實(shí)體由于所在的Server關(guān)閉Binder驅(qū)動(dòng)或異常退出而消失,引用者能做的就是要求Server在此刻給出通知 uint32 *ptr;需要得到死亡的通知Binder引用
BC_DEAD_BINDER 收到實(shí)體死亡通知書(shū)的進(jìn)程在刪除引用后用本命令告知驅(qū)動(dòng) void * cookie
  • 在這些命令中迎献,最常用的h是BC_TRANSACTION/BC_REPLY命令對(duì)瞎访,Binder請(qǐng)求和應(yīng)答數(shù)據(jù)就是通過(guò)這對(duì)命令發(fā)送給接受方。
  • 這對(duì)命令所承載的數(shù)據(jù)包由結(jié)構(gòu)體struct binder_transaction_data定義忿晕。Binder交互有同步和異步之分装诡。
  • 利用binder_transcation_data中的flag區(qū)域劃分银受。如果flag區(qū)域的TF_ONE_WAY位為1,則為異步交互鸦采,即client發(fā)送完請(qǐng)求交互即結(jié)束宾巍,Server端不再返回BC_REPLY數(shù)據(jù)包;否則Server會(huì)返回BC_REPLY數(shù)據(jù)包渔伯,Client端必須等待接受完數(shù)據(jù)包后才能完成一次交互顶霞。

6.2 BINDER_WRITE_READ:從Binder讀出數(shù)據(jù)

在Binder里讀出數(shù)據(jù)格式和向Binder中寫(xiě)入數(shù)據(jù)格式一樣,采用(消息ID+數(shù)據(jù))形式锣吼,并且多條消息可以連續(xù)存放选浑。

5713484-2a7b20599b2e4bc1.png

Binder讀操作消息ID

消息 含義 參數(shù)(arg)
BR_ERROR 發(fā)生內(nèi)部錯(cuò)誤(如內(nèi)存分配失敗) ----
BR_OK BR_NOOP 操作完成 ----
BR_SPAWN_LOOPER 消息用于接受方線程池管理。當(dāng)驅(qū)動(dòng)發(fā)現(xiàn)接收方所有線程都處于忙碌狀態(tài)且線程池中的線程總數(shù)沒(méi)有超過(guò)BINDER_SET_MAX_THREADS設(shè)置的最大線程時(shí)玄叠,向接收方發(fā)送該命令要求創(chuàng)建更多的線程以備接受數(shù)據(jù) ----
BR_TRANSCATION BR_REPLY 這兩條消息分別對(duì)應(yīng)發(fā)送方的 BC_TRANSACTION 和BC_REPLY古徒,表示當(dāng)前接受的數(shù)據(jù)是請(qǐng)求還是回復(fù) binder_transaction_data
BR_ACQUIRE_RESULT BR_ATTEMPT_ACQUIRE BR_FINISHED 尚未實(shí)現(xiàn) ----
BR_DEAD_REPLY 交互過(guò)程中如果發(fā)現(xiàn)對(duì)方進(jìn)程或線程已經(jīng)死亡則返回該消息 ----
BR_TRANSACTION_COMPLETE 發(fā)送方通過(guò)BC_TRRANSACTION或BC_REPLY發(fā)送完一個(gè)數(shù)據(jù)包后,都能收到該消息作為成功發(fā)送的反饋读恃。這和BR_REPLY不一樣隧膘,是驅(qū)動(dòng)告知發(fā)送方已經(jīng)發(fā)送成功,而不是Server端返回?cái)?shù)據(jù)寺惫。所以不管同步還是異步交互接收方都能獲得本消息疹吃。 ----
BR_INCREFS BR_ACQUIRE BR_RFLEASE BR_DECREFS 這組消息用于管理強(qiáng)/弱指針的引用計(jì)數(shù)。只有提供Binder實(shí)體的進(jìn)程才能收到這組消息 void *ptr : Binder實(shí)體在用戶空間中的指針 void **cookie:與該實(shí)體相關(guān)的附加數(shù)據(jù)
BR_DEAD_BINDER BR_CLEAR_DEATH_NOTIFICATION_DONE 向獲得Binder引用的進(jìn)程發(fā)送Binder實(shí)體死亡通知書(shū):收到死亡通知書(shū)的進(jìn)程接下來(lái)會(huì)返回 BC_DEAD_BINDER_DONE 確認(rèn) void *cookie 在使用BC_REQUEST_DEATH_NOTIFICATION注冊(cè)死亡通知時(shí)的附加參數(shù)
BR_FAILED_REPLY 如果發(fā)送非法引用號(hào)則返回該消息 ----

和寫(xiě)數(shù)據(jù)一樣西雀,其中最重要的消息是BR_TRANSACTION或BR_REPLY萨驶,表明收到一個(gè)格式為binder_transaction_data的請(qǐng)求數(shù)據(jù)包(BR_TRANSACTION或返回?cái)?shù)據(jù)包(BR_REPLY))

6.3 struct binder_transaction_data :收發(fā)數(shù)據(jù)包結(jié)構(gòu)

該結(jié)構(gòu)是Binder接收/發(fā)送數(shù)據(jù)包的標(biāo)準(zhǔn)格式,每個(gè)成員定義如下:

5713484-4dc6ef249047d46b.png
成員 含義
union{ size_t handle; void *ptr;} target艇肴; 對(duì)于發(fā)送數(shù)據(jù)包的一方腔呜,該成員指明發(fā)送目的地。由于目的地是遠(yuǎn)端豆挽,所以在這里填入的是對(duì)Binder實(shí)體的引用育谬,存放在target.handle中。如前述帮哈,Binder的引用在代碼中也叫句柄(handle)。 當(dāng)數(shù)據(jù)包到達(dá)接收方時(shí)锰镀,驅(qū)動(dòng)已將該成員修改成Binder實(shí)體娘侍,即指向 Binder對(duì)象內(nèi)存的指針,使用target.ptr來(lái)獲取泳炉。該指針是接受方在將Binder實(shí)體傳輸給其他進(jìn)程時(shí)提交給驅(qū)動(dòng)的憾筏,驅(qū)動(dòng)程序能夠自動(dòng)將發(fā)送方填入的引用轉(zhuǎn)換成接收方的Binder對(duì)象的指針,故接收方可以直接將其當(dāng)對(duì)象指針來(lái)使用(通常是將其reinpterpret_cast相應(yīng)類)
void *cookie花鹅; 發(fā)送方忽略該成員氧腰;接收方收到數(shù)據(jù)包時(shí),該成員存放的是創(chuàng)建Binder實(shí)體時(shí)由該接收方自定義的任意數(shù)值,做為與Binder指針相關(guān)的額外信息存放在驅(qū)動(dòng)中古拴。驅(qū)動(dòng)基本上不關(guān)心該成員
unsigned int code ; 該成員存放收發(fā)雙方約定的命令碼箩帚,驅(qū)動(dòng)完全不關(guān)心該成員的內(nèi)容。通常是Server端的定義的公共接口函數(shù)的編號(hào)
unsigned int code; 與交互相關(guān)的標(biāo)志位黄痪,其中最重要的是TF_ONE_WAY位紧帕。如果該位置上表明這次交互是異步的,Server端不會(huì)返回任何數(shù)據(jù)桅打。驅(qū)動(dòng)利用該位決定是否構(gòu)建與返回有關(guān)的數(shù)據(jù)結(jié)構(gòu)是嗜。另外一位TF_ACCEPT_FDS是處于安全考慮,如果發(fā)起請(qǐng)求的一方不希望在收到回復(fù)中接收文件的Binder可以將位置上挺尾。因?yàn)槭盏揭粋€(gè)文件形式的Binder會(huì)自動(dòng)為接收方打開(kāi)一個(gè)文件鹅搪,使用該位可以防止打開(kāi)文件過(guò)多
pid_t send_pid uid_t sender_euid 該成員存放發(fā)送方的進(jìn)程ID和用戶ID,由驅(qū)動(dòng)負(fù)責(zé)填入遭铺,接收方可以讀取該成員獲取發(fā)送方的身份丽柿。
size_t data_size 驅(qū)動(dòng)一般情況下不關(guān)心data.buffer里存放了什么數(shù)據(jù)。但如果有Binder在其中傳輸則需要將其對(duì)應(yīng)data.buffer的偏移位置指出來(lái)讓驅(qū)動(dòng)知道掂僵。有可能存在多個(gè)Binder同時(shí)在數(shù)據(jù)中傳遞航厚,所以須用數(shù)組表示所有偏移位置。本成員表示該數(shù)組的大小锰蓬。
union{ struct{ const void *buffer; const void * offset; } ptr; uint8_t buf[8];} data; data.buffer存放要發(fā)送或接收到的數(shù)據(jù)幔睬;data.offsets指向Binder偏移位置數(shù)組,該數(shù)組可以位于data.buffer中芹扭,也可以在另外的內(nèi)存空間中麻顶,并無(wú)限制。buf[8]是為了無(wú)論保證32位還是64位平臺(tái)舱卡,成員data的大小都是8字節(jié)辅肾。
  • offsets_size和data.offsets兩個(gè)成員,這是Binder通信有別于其他IPC的地方轮锥。
  • Binder采用面向?qū)ο?/strong>的設(shè)計(jì)思想矫钓,一個(gè)Binder實(shí)體可以發(fā)送給其他進(jìn)程從而建立許多跨進(jìn)程的引用;另外這些引用也可以在進(jìn)程之間傳遞舍杜,就像java將一個(gè)引用賦值給另外一個(gè)引用一樣新娜。為Binder在不同進(jìn)程中創(chuàng)建引用必須有驅(qū)動(dòng)參與,由驅(qū)動(dòng)在內(nèi)核創(chuàng)建并注冊(cè)相關(guān)的數(shù)據(jù)結(jié)構(gòu)后接收方才能使用該引用既绩。而且這些引用可以是強(qiáng)類型的概龄,需要驅(qū)動(dòng)為其維護(hù)引用計(jì)數(shù)。
  • 然后這些跨進(jìn)程傳遞的Binder混雜在應(yīng)用程序發(fā)送的數(shù)據(jù)包里饲握,數(shù)據(jù)格式由用戶定義私杜,如果不把他們一一標(biāo)記出來(lái)告知驅(qū)動(dòng)蚕键,驅(qū)動(dòng)將無(wú)法從數(shù)據(jù)中將他們提取出來(lái)。
  • 使用數(shù)組data.offsets存放用戶數(shù)據(jù)中每個(gè)Binder相對(duì)于data.buffer的偏移量衰粹,用offersets_size表示這個(gè)數(shù)組的大小锣光。驅(qū)動(dòng)在發(fā)送數(shù)據(jù)包時(shí)會(huì)根據(jù)data.offsets和offset_size將散落于data.buffer中的Binder找出來(lái)并一一為它們創(chuàng)建相關(guān)的數(shù)據(jù)結(jié)構(gòu)。

7 Binder的整體架構(gòu)

5713484-b1f3856acf1e2384.png

參考

Android跨進(jìn)程通信IPC之6——Binder框架

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寄猩,一起剝皮案震驚了整個(gè)濱河市嫉晶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌田篇,老刑警劉巖替废,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泊柬,居然都是意外死亡椎镣,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)兽赁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)状答,“玉大人,你說(shuō)我怎么就攤上這事刀崖【疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵亮钦,是天一觀的道長(zhǎng)馆截。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蜂莉,這世上最難降的妖魔是什么蜡娶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮映穗,結(jié)果婚禮上窖张,老公的妹妹穿的比我還像新娘。我一直安慰自己蚁滋,他們只是感情好宿接,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著辕录,像睡著了一般澄阳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踏拜,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音低剔,去河邊找鬼速梗。 笑死肮塞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姻锁。 我是一名探鬼主播枕赵,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼位隶!你這毒婦竟也來(lái)了拷窜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤涧黄,失蹤者是張志新(化名)和其女友劉穎篮昧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體笋妥,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懊昨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了春宣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酵颁。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖月帝,靈堂內(nèi)的尸體忽然破棺而出躏惋,到底是詐尸還是另有隱情,我是刑警寧澤嚷辅,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布簿姨,位于F島的核電站,受9級(jí)特大地震影響潦蝇,放射性物質(zhì)發(fā)生泄漏款熬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一攘乒、第九天 我趴在偏房一處隱蔽的房頂上張望贤牛。 院中可真熱鬧,春花似錦则酝、人聲如沸殉簸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)般卑。三九已至,卻和暖如春爽雄,著一層夾襖步出監(jiān)牢的瞬間蝠检,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工挚瘟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叹谁,地道東北人饲梭。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像焰檩,于是被迫代替她去往敵國(guó)和親憔涉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容