[TOC]
# 1\. Binder是什么
在Android中Binder是跨進程通信方式。不過從不同角度來開,binder也可以有如下理解:
1,從進程間通信的角度看,Binder 是一種進程間通信的機制; 2,從 Server 進程的角度看,Binder 指的是 Server 中的 Binder 實體對象; 3,從 Client 進程的角度看,Binder 指的是對 Binder 代理對象,是 Binder 實體對象的一個遠程代理 4,從傳輸過程的角度看,Binder 是一個可以跨進程傳輸的對象;傳輸過程中,Binder 驅動會對這個跨越進程的對象,自動完成代理對象和本地對象之間的轉換。
# 2\. Binder優勢
Linux提供了管道、消息隊列、共享內存和 Socket 等 IPC 機制。
1. 管道/消息隊列:信息復制兩次,額外的CPU消耗;不合適頻繁或信息量大的通信;
2. 共享內存:無須復制,共享緩沖區直接附加到進程虛擬地址空間,速度快;但進程間的同步問題操作系統無法實現,必須各進程利用同步工具解決;
3. Socket:作為更通用的接口,傳輸效率低(涉及io讀寫),主要用于不通機器或跨網絡的通信;
4. 信號量:常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
5. 信號: 不適用于信息交換,更適用于進程中斷控制,比如非法內存訪問,殺死某個進程等;
## 2.1 性能:
Binder數據拷貝只需要一次,而管道、消息隊列、Socket都需要2次,共享不需要內存拷貝;從性能角度看,Binder性能僅次于共享內存。
## 2.2 穩定性:
Binder是基于C/S架構的,Client端有什么需求,直接發送給Server端去完成,架構清晰,Server端與Client端相對獨立,穩定性較好;
而共享內存實現方式復雜,沒有客戶與服務端之別,需要充分考慮到訪問臨界資源的并發同步問題,否則可能會出現死鎖等問題;從這穩定性角度看,Binder架構優越于共享內存。
## 2.3 安全性:
傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;(比如socket 只能由用戶在數據包中填入 UID/PID))。
Android系統中對外只暴露Client端,Client端將任務發送給Server端,Server端會根據權限控制策略,判斷UID/PID是否滿足訪問權限,目前權限控制很多時候是通過彈出權限詢問對話框,讓用戶選擇是否運行。
注意:Binder是為Android這類系統而生(主要從安全行考慮),并非Linux現有的IPC機制不好,只是根據不通的場景會選擇不不同的IPC機制,例如:
1,Android OS中的Zygote進程的IPC采用的是Socket(套接字)機制;
參考:[blog.csdn.net/qq\_39037047…](https://link.juejin.cn?target=https%3A%2F%2Fblog.csdn.net%2Fqq_39037047%2Farticle%2Fdetails%2F88066589 "https://blog.csdn.net/qq_39037047/article/details/88066589")
2,Android中的Kill Process采用的signal(信號)機制;
3,而Binder更多則用在system\_server進程與上層App層的IPC交互(主要從安全行考慮)。
# 3\. Binder 通信原理
## 3.1 進程空間劃分
進程間,用戶空間的數據不可共享,所以用戶空間 = 不可共享空間
進程間,內核空間的數據可共享,所以內核空間 = 可共享空間
所有進程共用1個內核空間
進程內 用戶空間 & 內核空間 進行交互 需通過 系統調用,主要通過函數:
1,copy\_from\_user():將用戶空間的數據拷貝到內核空間
2,copy\_to\_user():將內核空間的數據拷貝到用戶空間

## 3.2 Binder驅動

## 3.3 內存映射

首先在內核虛擬地址空間,申請一塊與用戶虛擬內存相同大小的內存;然后再申請1個page大小的物理內存,再將同一塊物理內存分別映射到內核虛擬地址空間和用戶虛擬內存空間,從而實現了用戶空間的Buffer和內核空間的Buffer同步操作的功能。
## 3.4 Binder通信原理

1,Binder驅動在內核空間創建一個數據接收緩存區;
2,實現地址映射關系,將內核緩存區和接收進程地址空間映射到Binde創建一個數據接收緩存區;
3,發送方進程通過系統調用 copy\_from\_user() 將數據 copy 到內核緩存區,由于內核緩存區和接收進程的地址空間存在內存映射,因此也就相當于把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。
**問題:為啥不能直接將內核緩存區映射到接收進程地址空間,而需要再開辟一個數據接收緩存區???**
我的理解是:binder開辟的數據接受緩存區就是就是開辟一塊物理內存,然后將內核緩存區和接收進程地址空間映射。
# 4\. Binder通信模型
## 4.1 通信模型


1,一個進程使用 BINDER\_SET\_CONTEXT\_MGR 命令通過 Binder 驅動將自己注冊成為 ServiceManager;
2,Server 通過驅動向 ServiceManager 中注冊 Binder(Server 中的 Binder 實體),即注冊(可對外提供的)服務。驅動為這個 Binder 創建位于內核中的實體節點以及 ServiceManager 對實體的引用,將名字以及新建的引用打包傳給 ServiceManager,ServiceManger 將其填入查找表。
3,Client 通過名字,在 Binder 驅動的幫助下從 ServiceManager 中獲取到對 Binder 實體的引用,通過這個引用就能實現和 Server 進程的通信。
注意:
1,ServiceManager進程是使用BINDER\_SET\_CONTEXT\_MGR將自己注冊成ServiceManager,并會創建一個Binder 實體
2,這個 Binder 實體的引用在所有 Client 中都固定為 0 ,無需通過其它手段獲得。也就是說,一個 Server 想要向 ServiceManager 注冊自己的 Binder 就必須通過這個 0 號引用和 ServiceManager 的 Binder 通信。
## 4.2 系統服務和自定義服務
1,系統服務會往ServiceManager注冊,ServiceManager運行在單獨的進程里,客戶端進程需要先向ServiceManager里請求IBinder,再使用IBinder獲取關聯接口進而使用系統服務。
2,自定義服務所在進程開啟后,暴露出IBinder。客戶端通過綁定服務端進程里的Service,將IBinder跨進程傳遞至客戶端,客戶端再使用IBinder獲取關聯接口進而使用自定義服務。此過程沒有借助于ServiceManager。
參考:[www.jianshu.com/p/b39ffcbcb…](https://link.juejin.cn?target=https%3A%2F%2Fwww.jianshu.com%2Fp%2Fb39ffcbcb7b7 "https://www.jianshu.com/p/b39ffcbcb7b7")
# 5\. Android Binder 通信代碼理解
## 5.1 Binder相關類
1,IBinder : IBinder 是一個接口,代表了一種跨進程通信的能力。只要實現了這個借口,這個對象就能跨進程傳輸。
2,IInterface : IInterface 代表 Server 進程對象具備什么樣的能力(能提供哪些方法,其實對應的就是 AIDL 文件中定義的接口)
3,Binder : Java 層的 Binder 類,代表 Binder 本地對象。
4,BinderProxy :表clientd端,遠程 Binder 對象的本地代理;
這兩個類都繼承自 IBinder, 因而都具有跨進程傳輸的能力;實際上,在跨越進程的時候,Binder 驅動會自動完成這兩個對象的轉換。
5,Stub : AIDL 的時候,編譯工具會給我們生成一個名為 Stub 的靜態內部類;這個類繼承了 Binder, 說明它是一個 Binder 本地對象,它實現了 IInterface 接口,表明它具有 Server 提供給 Client 的能力;Stub 是一個抽象類,具體的 IInterface 的相關實現需要開發者自己實現。
## 5.2 aidl使用流程圖:

# 6\. 參考
[Android Binder 原理](https://juejin.cn/post/6975522311625506852)
- Android
- 四大組件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介紹
- MessageQueue詳細
- 啟動流程
- 系統啟動流程
- 應用啟動流程
- Activity啟動流程
- View
- view繪制
- view事件傳遞
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大數據
- Binder小結
- Android組件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 遷移與修復
- Sqlite內核
- Sqlite優化v2
- sqlite索引
- sqlite之wal
- sqlite之鎖機制
- 網絡
- 基礎
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP進化圖
- HTTP小結
- 實踐
- 網絡優化
- Json
- ProtoBuffer
- 斷點續傳
- 性能
- 卡頓
- 卡頓監控
- ANR
- ANR監控
- 內存
- 內存問題與優化
- 圖片內存優化
- 線下內存監控
- 線上內存監控
- 啟動優化
- 死鎖監控
- 崩潰監控
- 包體積優化
- UI渲染優化
- UI常規優化
- I/O監控
- 電量監控
- 第三方框架
- 網絡框架
- Volley
- Okhttp
- 網絡框架n問
- OkHttp原理N問
- 設計模式
- EventBus
- Rxjava
- 圖片
- ImageWoker
- Gilde的優化
- APT
- 依賴注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 協程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 運行期Java-hook技術
- 編譯期hook
- ASM
- Transform增量編譯
- 運行期Native-hook技術
- 熱修復
- 插件化
- AAB
- Shadow
- 虛擬機
- 其他
- UI自動化
- JavaParser
- Android Line
- 編譯
- 疑難雜癥
- Android11滑動異常
- 方案
- 工業化
- 模塊化
- 隱私合規
- 動態化
- 項目管理
- 業務啟動優化
- 業務架構設計
- 性能優化case
- 性能優化-排查思路
- 性能優化-現有方案
- 登錄
- 搜索
- C++
- NDK入門
- 跨平臺
- H5
- Flutter
- Flutter 性能優化
- 數據跨平臺