跟著小白一起學(xué)鴻蒙# Binder機(jī)制剖析和使用
??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
原理
Binder概述
- 什么是Binder
Binder最開始是IPC工具,起源于OpenBinder項(xiàng)目,發(fā)展于Android項(xiàng)目,現(xiàn)在已經(jīng)和入LinuxKernel,目前演變成RPC工具,可以使當(dāng)前進(jìn)程調(diào)用另一個(gè)進(jìn)程的函數(shù)向自身函數(shù)一樣簡(jiǎn)單。
Binder是解決進(jìn)程間通訊問題的框架
- Binder能干什么
OpenHarmony里的對(duì)應(yīng)層次就是:
- 驅(qū)動(dòng):kernel/linux/linux-xxx/drivers/android/binderXXX
- 服務(wù):foundation/communication/ipc
- 框架:各種NAPI里面和對(duì)應(yīng)的服務(wù)接口:如foundation/communication/xxx/frameworks/js/napi/xxx和foundation/communication/xxx/services/bluetooth/service/xxx
在OpenHarmony上表現(xiàn)的功能是:
- 提供客戶端-服務(wù)器(Client-Server)模型,服務(wù)請(qǐng)求方(Client)可獲取提供服務(wù)提供方(Server)的代理 (Proxy),并通過此代理讀寫數(shù)據(jù)來實(shí)現(xiàn)進(jìn)程間的數(shù)據(jù)通信。通常,系統(tǒng)能力(System Ability)Server側(cè)會(huì)先注冊(cè)到系統(tǒng)能力管理者(System Ability Manager,縮寫SAMgr)中,SAMgr負(fù)責(zé)管理這些SA并向Client提供相關(guān)的接口。Client要和某個(gè)具體的SA通信,必須先從SAMgr中獲取該SA的代理,然后使用代理和SA通信。三方應(yīng)用可以使用FA提供的接口綁定服務(wù)提供方的Ability,獲取代理,進(jìn)行通信。
在OpenHarmony里的限制是:
- 單個(gè)設(shè)備上跨進(jìn)程通信時(shí),傳輸?shù)臄?shù)據(jù)量最大約為1MB,過大的數(shù)據(jù)量請(qǐng)使用匿名共享內(nèi)存。
- 不支持把跨設(shè)備的Proxy對(duì)象傳遞回該P(yáng)roxy對(duì)象所指向的Stub對(duì)象所在的設(shè)備。
- Binder原理是什么
Binder是C/S架構(gòu)的進(jìn)程間通訊機(jī)制。特點(diǎn)如下:
- 用戶空間運(yùn)行:Client,Service和Service Manager;內(nèi)核空間運(yùn)行:Binder Driver
- Client,Server和Service Manager通過系統(tǒng)調(diào)用open,mmap和ioctl來訪問設(shè)備文件/dev/binder。從而實(shí)現(xiàn)進(jìn)程間通信
- 功能詳細(xì)如下:
- 對(duì)應(yīng)文件如下
- Binder通信過程介紹
- Service使用 BINDER_SET_CONTEXT_MGR命令通過Ioctl將自己注冊(cè)成為ServiceMannager
- Client向Binder驅(qū)動(dòng)發(fā)起獲取服務(wù)的請(qǐng)求,Binder驅(qū)動(dòng)通過Client需要獲取服務(wù)的名稱,從ServiceManager中獲取對(duì)Binder實(shí)體的引用,通過獲得到的引用就能實(shí)現(xiàn)和Server進(jìn)程的通信
- IPC通信過程介紹
- 首先Binder驅(qū)動(dòng)在內(nèi)核空間創(chuàng)建一個(gè)數(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)系
- Client通過系統(tǒng)調(diào)用copy_from_user()將數(shù)據(jù)拷貝到內(nèi)核中的內(nèi)核緩存區(qū),由于內(nèi)核緩存區(qū)和Service的用戶空間存在內(nèi)存映射,所以Service進(jìn)程的用戶空間也有了此數(shù)據(jù),這就完成一次跨進(jìn)程通信
角色說明
- Client進(jìn)程:使用服務(wù)的進(jìn)程
- Server進(jìn)程:提供服務(wù)的進(jìn)程
- Service Manager進(jìn)程:管理Service注冊(cè)與查詢(將字符形式的Binder名字轉(zhuǎn)化成Client中對(duì)該Binder的引用)
- Binder驅(qū)動(dòng):虛擬設(shè)備驅(qū)動(dòng),是連接Service進(jìn)程,Client進(jìn)程和Service Manager的橋梁,具體作用為:1.傳遞進(jìn)程間的數(shù)據(jù),通過內(nèi)存映射。2.實(shí)現(xiàn)線程控制:采用Binder的線程池,并由Binder驅(qū)動(dòng)自身進(jìn)行管理。
- Binder怎么用
JS側(cè)依賴
Native側(cè)編譯依賴
sdk依賴:
此外, IPC/RPC依賴的refbase實(shí)現(xiàn)在公共基礎(chǔ)庫下,請(qǐng)?jiān)黾訉?duì)utils的依賴:
JS側(cè)實(shí)現(xiàn)跨進(jìn)程通信基本步驟:
獲取代理
使用ohos.ability.featureAbility提供的connectAbility方法綁定Ability,在參數(shù)里指定要綁定的Ability所在應(yīng)用的包名、組件名,如果是跨設(shè)備的情況,還需要指定所在設(shè)備的NetworkId。用戶需要在服務(wù)端的onConnect方法里返回一個(gè)繼承自ohos.rpc.RemoteObject的對(duì)象,此對(duì)象會(huì)在其onRemoteMessageRequest方法里接收到請(qǐng)求。
發(fā)送請(qǐng)求
客戶端在connectAbility參數(shù)指定的回調(diào)函數(shù)接收到代理對(duì)象后,使用ohos.rpc模塊提供的方法完成RPC通信,其中MessageParcel提供了讀寫各種類型數(shù)據(jù)的方法,IRemoteObject提供了發(fā)送請(qǐng)求的方法,RemoteObject提供了處理請(qǐng)求的方法onRemoteRequest,用戶需要重寫。
Native側(cè)實(shí)現(xiàn)跨進(jìn)程通信的基本步驟:
定義接口類
接口類繼承IRemoteBroker,定義描述符、業(yè)務(wù)函數(shù)和消息碼。
實(shí)現(xiàn)服務(wù)提供端(Stub)
Stub繼承IRemoteStub(Native),除了接口類中未實(shí)現(xiàn)方法外,還需要實(shí)現(xiàn)AsObject方法及OnRemoteRequest方法。
實(shí)現(xiàn)服務(wù)請(qǐng)求端(Proxy)
Proxy繼承IRemoteProxy(Native),封裝業(yè)務(wù)函數(shù),調(diào)用SendRequest將請(qǐng)求發(fā)送到Stub。
注冊(cè)SA
服務(wù)提供方所在進(jìn)程啟動(dòng)后,申請(qǐng)SA的唯一標(biāo)識(shí),將Stub注冊(cè)到SAMgr。
通過SA的標(biāo)識(shí)和設(shè)備NetworkId,從SAMgr獲取Proxy,通過Proxy實(shí)現(xiàn)與Stub的跨進(jìn)程通信。