以下文章參考 https://zhuanlan.zhihu.com/p/35519585介时,《Android藝術(shù)開發(fā)探索》
首先像聲明,Binder 的復(fù)雜程度肯定不是一篇文章能說清楚的厢汹,之所以寫這篇文章,是在博客,書上學(xué)習(xí)到后歌焦,能讓自己有一個(gè)概念,希望深入理解 Binder 的可以自行參考網(wǎng)上文章砚哆。
什么是 Binder?
我的理解就是:是一種進(jìn)程間的通訊機(jī)制
為什么是 Binder?
大家都知道独撇,Android 是基于 Linux 內(nèi)核開發(fā)的,Linux 本身就提供了多種進(jìn)程間通訊的機(jī)制躁锁,如管道(Pipe)纷铣、信號(Signal)、消息隊(duì)列(Message)战转、共享內(nèi)存(Share Memory)和 Socket 等
原因:
其他通信方式存在 安全性搜立,性能等問題
性能:
Socket 作為一款通用接口,其傳輸效率低槐秧,開銷大啄踊,主要用在跨網(wǎng)絡(luò)的進(jìn)程間通信和本機(jī)上進(jìn)程間的低速通信。消息隊(duì)列和管道采用存儲-轉(zhuǎn)發(fā)方式刁标,即數(shù)據(jù)先從發(fā)送方緩存區(qū)拷貝到內(nèi)核開辟的緩存區(qū)中颠通,然后再從內(nèi)核緩存區(qū)拷貝到接收方緩存區(qū),至少有兩次拷貝過程膀懈。共享內(nèi)存雖然無需拷貝顿锰,但控制復(fù)雜,難以使用启搂。Binder 只需要一次數(shù)據(jù)拷貝硼控,性能上僅次于共享內(nèi)存。
進(jìn)程間通訊方式 | 拷貝次數(shù) |
---|---|
管道 | 2 |
消息隊(duì)列 | 2 |
Socket | 2 |
Binner | 1 |
共享內(nèi)存 | 0 |
安全性:
傳統(tǒng) IPC 接收方無法獲得對方可靠的進(jìn)程用戶ID/進(jìn)程ID(UID/PID)胳赌,從而無法鑒別身份牢撼,而Binder機(jī)制為每個(gè)進(jìn)程分配了UID/PID且在Binder通信時(shí)會根據(jù)UID/PID進(jìn)行身份鑒別
基本的跨進(jìn)程概念
-
進(jìn)程隔離:
進(jìn)程與進(jìn)程間內(nèi)存是不共享的 -
進(jìn)程空間劃分:用戶空間(User Space)/內(nèi)核空間(Kernel Space)
內(nèi)核空間(Kernel)是系統(tǒng)內(nèi)核運(yùn)行的空間,用戶空間(User Space)是用戶程序運(yùn)行的空間疑苫。為了保證安全性熏版,它們之間是隔離的。 -
系統(tǒng)調(diào)用:用戶態(tài)/內(nèi)核態(tài)
當(dāng)一個(gè)任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時(shí)缀匕,稱進(jìn)程處于內(nèi)核運(yùn)行態(tài)(內(nèi)核態(tài))
當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼的時(shí)候纳决,我們稱其處于用戶運(yùn)行態(tài)(用戶態(tài))
系統(tǒng)調(diào)用主要通過如下兩個(gè)函數(shù)來實(shí)現(xiàn):
copy_from_user() :將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間
copy_to_user() :將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間
傳統(tǒng)IPC原理
- 發(fā)送方將要發(fā)送數(shù)據(jù)的放在用戶空間內(nèi)存緩存區(qū)
- 調(diào)用 copyfromuser() 函數(shù)將數(shù)據(jù)從用戶空間的內(nèi)存緩存區(qū)拷貝到內(nèi)核空間的內(nèi)核緩存區(qū)中
- 接收方進(jìn)程在接收數(shù)據(jù)時(shí)在自己的用戶空間開辟一塊內(nèi)存緩存區(qū)
-
內(nèi)核程序調(diào)用 copytouser() 函數(shù)將數(shù)據(jù)從內(nèi)核緩存區(qū)拷貝到接收進(jìn)程的內(nèi)存緩存區(qū)
image
Binder IPC 底層通訊原理
IPC 過程
- Binder 驅(qū)動(dòng)創(chuàng)建一塊數(shù)據(jù)接收緩存區(qū)
- 在內(nèi)核空間開辟一塊內(nèi)核緩存區(qū),建立內(nèi)核緩存區(qū)和內(nèi)核中數(shù)據(jù)接收緩存區(qū)之間的映射關(guān)系乡小,以及內(nèi)核中數(shù)據(jù)接收緩存區(qū)和接收進(jìn)程用戶空間地址的映射關(guān)系阔加;
-
發(fā)送方進(jìn)程通過系統(tǒng)調(diào)用 copyfromuser() 將數(shù)據(jù) copy 到內(nèi)核中的內(nèi)核緩存區(qū),由于內(nèi)核緩存區(qū)和接收進(jìn)程的用戶空間存在內(nèi)存映射满钟,因此也就相當(dāng)于把數(shù)據(jù)發(fā)送到了接收進(jìn)程的用戶空間胜榔,這樣便完成了一次進(jìn)程間的通信胳喷。
image
Binder 實(shí)現(xiàn)層
首先我們應(yīng)該知道 Binder 是 C/S 架構(gòu),他的組成主要有 Client夭织、Server吭露、ServiceManager, Binder 驅(qū)動(dòng) ,其中 Client、Server尊惰、ServiceManager 是運(yùn)行在 用戶空間層讲竿,而 Binder 驅(qū)動(dòng) 自然是內(nèi)核層了。
通信過程
- 首先弄屡,一個(gè)進(jìn)程使用 BINDERSETCONTEXT_MGR 命令通過 Binder 驅(qū)動(dòng)將自己注冊成為 ServiceManager
- Server 向 Service Manager 中注冊 Binder (Server 中的 Binder 實(shí)體)表明可以對外提供服務(wù)
- Client 向 Service Manager 獲取到對Binder 實(shí)體的引用
- 通過這個(gè)引用實(shí)現(xiàn) Client 和 Server 的進(jìn)程通信
Binder 通信中的代理模式
由上面我們知道了 跨進(jìn)程通信是借住了 Binder 驅(qū)動(dòng)完成的题禀,由于 Client 和 Server 是兩個(gè)不同的進(jìn)程,當(dāng) Client 想要 Server 某個(gè)對象的話膀捷,是沒辦法直接使用的迈嘹。所以既然跨進(jìn)程是借住 Binder 驅(qū)動(dòng) 完成的,因此在數(shù)據(jù)經(jīng)過 Binder 驅(qū)動(dòng)的時(shí)候驅(qū)動(dòng)會對數(shù)據(jù)進(jìn)行一層轉(zhuǎn)換全庸,當(dāng) A 進(jìn)程想要獲取 B 進(jìn)程的 object 時(shí)秀仲,驅(qū)動(dòng)并不會把真正的 object 返回給 A ,而是返回一個(gè)跟 object 看起來一模一樣的代理對象 objectProxy ,這個(gè) objectProxy 具有和 object 一摸一樣的方法壶笼,但是這些方法并沒有 B 進(jìn)程中 object 對象那些方法的能力神僵,這些方法只需要把請求參數(shù)交給驅(qū)動(dòng)即可。對于 A 進(jìn)程來說和直接調(diào)用 object 中的方法是一樣的拌消。
Binder 的定義
現(xiàn)在我們可以對 Binder 做個(gè)更加全面的定義了:
- 從進(jìn)程間通信的角度看挑豌,Binder 是一種進(jìn)程間通信的機(jī)制;
- 從 Server 進(jìn)程的角度看墩崩,Binder 指的是 Server 中的 Binder 實(shí)體對象;
- 從 Client 進(jìn)程的角度看侯勉,Binder 指的是對 Binder 代理對象鹦筹,是 Binder 實(shí)體對象的一個(gè)遠(yuǎn)程代理
- 從傳輸過程的角度看,Binder 是一個(gè)可以跨進(jìn)程傳輸?shù)膶ο笾访玻籅inder 驅(qū)動(dòng)會對這個(gè)跨越進(jìn)程邊界的對象對一點(diǎn)點(diǎn)特殊處理铐拐,自動(dòng)完成代理對象和本地對象之間的轉(zhuǎn)換。