跟著小白一起學鴻蒙# Binder機制剖析和使用

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





































