Binder通信采用C/S架構(gòu),從組件視角來(lái)說(shuō),包含Client、Server、ServiceManager以及binder驅(qū)動(dòng)。架構(gòu)圖如下所示:

圖中的Client,Server,Service Manager之間交互都是虛線表示,是由于它們彼此之間不是直接交互的,而是都通過(guò)與Binder驅(qū)動(dòng)進(jìn)行交互的,從而實(shí)現(xiàn)IPC通信方式。
關(guān)于Binder驅(qū)動(dòng)設(shè)備
這部分涉及到Linux設(shè)備驅(qū)動(dòng)的開(kāi)發(fā),如有興趣可參考Binder系列1—Binder Driver初探。這里僅簡(jiǎn)單闡述Binder驅(qū)動(dòng)的原理。
binder作為虛擬設(shè)備,沒(méi)有直接操作硬件,只是對(duì)設(shè)備內(nèi)存的處理。主要完成以下幾件事
- 初始化(binder_init):創(chuàng)建/dev/binder設(shè)備節(jié)點(diǎn)
- 打開(kāi) (binder_open):獲取Binder Driver的文件描述
- 映射(binder_mmap):內(nèi)核中分配內(nèi)存,用于存放數(shù)據(jù)
- 數(shù)據(jù)操作(binder_ioctl):將IPC數(shù)據(jù)作為參數(shù)傳給Binder Driver
binder_open創(chuàng)建了一個(gè)對(duì)象保存當(dāng)前進(jìn)程信息,并將這個(gè)對(duì)象加入一個(gè)全局鏈表。
binder_mmap首先在內(nèi)核虛擬地址空間,申請(qǐng)一塊與用戶虛擬內(nèi)存相同大小的內(nèi)存;然后再申請(qǐng)1個(gè)page大小的物理內(nèi)存,再將同一塊物理內(nèi)存分別映射到內(nèi)核虛擬地址空間和用戶虛擬內(nèi)存空間,從而實(shí)現(xiàn)了用戶空間的Buffer和內(nèi)核空間的Buffer同步操作的功能。

經(jīng)常聽(tīng)說(shuō)Binder進(jìn)程間通信的高效率,正是源于binder_mmap。通過(guò)Binder進(jìn)行進(jìn)程間通信時(shí),只會(huì)發(fā)生一次內(nèi)存拷貝。因?yàn)椋?dāng)Client端與Server端發(fā)送數(shù)據(jù)時(shí),Client先從自己的進(jìn)程空間把IPC通信數(shù)據(jù)拷貝到內(nèi)核空間,而Server與內(nèi)核共享數(shù)據(jù),不再需要拷貝數(shù)據(jù),而是通過(guò)內(nèi)存地址空間的偏移量,即可獲悉內(nèi)存地址,整個(gè)過(guò)程只發(fā)生一次內(nèi)存拷貝。
binder_ioctl負(fù)責(zé)在兩個(gè)進(jìn)程間收發(fā)IPC數(shù)據(jù)和IPC reply數(shù)據(jù)。

關(guān)于ServiceManager
- 本身也是一個(gè)的Server
- 主要職責(zé)是管理其他Server
- 是Binder機(jī)制的守護(hù)進(jìn)程
ServiceManager啟動(dòng)流程:
- 打開(kāi)binder驅(qū)動(dòng),并調(diào)用mmap()方法分配128k的內(nèi)存映射空間
- 通知binder驅(qū)動(dòng)使其成為守護(hù)進(jìn)程
- 進(jìn)入循環(huán)狀態(tài),等待Client端的請(qǐng)求
ServiceManager可以做什么:
- 注冊(cè)服務(wù)(addService)
- 驗(yàn)證selinux權(quán)限,判斷進(jìn)程是否有權(quán)注冊(cè)或查看指定服務(wù)
- 如果服務(wù)已注冊(cè),則不再添加
- 注冊(cè)服務(wù)時(shí),普通服務(wù)時(shí)作為Client,ServiceManager作為Server
- 獲取服務(wù)(getService)
- Client首先獲取ServiceManager
- 再通過(guò)字符串名稱來(lái)查找對(duì)應(yīng)的Service
-
defaultServiceManager()是一個(gè)單例模式,用于獲取ServiceMananger
總結(jié)
到此為止,已經(jīng)基本講明了ServiceManager和Binder。如果對(duì)于一個(gè)普通的Server怎么注冊(cè)和被獲取感興趣,還可繼續(xù)閱讀Binder系列5—注冊(cè)服務(wù)(addService)
和Binder系列6—獲取服務(wù)(getService)