Bindler 入門(mén)

參考:
https://juejin.im/post/5acccf845188255c3201100f
http://www.itdecent.cn/p/1eff5a13000d
https://blog.csdn.net/andywuchuanlong/article/details/43937493
https://blog.csdn.net/carson_ho/article/details/73560642

Binder 概述

Binder 是一種進(jìn)程間通信機(jī)制,基于開(kāi)源的 OpenBinder 實(shí)現(xiàn);
字面上來(lái)解釋 Binder 有膠水、粘合劑的意思,顧名思義就是粘和不同的進(jìn)程,使之實(shí)現(xiàn)通信。

為什么必須理解 Binder ?

作為 Android 工程師的你,是不是常常會(huì)有這樣的疑問(wèn):

  • 為什么 Activity 間傳遞對(duì)象需要序列化?
  • Activity 的啟動(dòng)流程是什么樣的?
  • 四大組件底層的通信機(jī)制是怎樣的?
  • AIDL 內(nèi)部的實(shí)現(xiàn)原理是什么?
  • 插件化編程技術(shù)應(yīng)該從何學(xué)起?等等...

這些問(wèn)題的背后都與 Binder 有莫大的關(guān)系,要弄懂上面這些問(wèn)題理解 Bidner 通信機(jī)制是必須的。
binder使用場(chǎng)景簡(jiǎn)介:

1, 我們知道 Android 應(yīng)用程序是由 Activity、Service、Broadcast Receiver 和 Content Provide 四大組件中的一個(gè)或者多個(gè)組成的。
2, 有時(shí)這些組件運(yùn)行在同一進(jìn)程,有時(shí)運(yùn)行在不同的進(jìn)程。
3, 這些進(jìn)程間的通信就依賴(lài)于 Binder IPC 機(jī)制。
4, 不僅如此,Android 系統(tǒng)對(duì)應(yīng)用層提供的各種服務(wù)如:ActivityManagerService、PackageManagerService 等都是基于 Binder IPC 機(jī)制來(lái)實(shí)現(xiàn)的。
5, Binder 機(jī)制在 Android 中的位置非常重要,毫不夸張的說(shuō)理解 Binder 是邁向 Android 高級(jí)工程的第一步。

為什么是 Binder ?

Android 系統(tǒng)是基于 Linux 內(nèi)核的,Linux 已經(jīng)提供了管道、消息隊(duì)列、共享內(nèi)存和 Socket 等 IPC 機(jī)制。那為什么 Android 還要提供 Binder 來(lái)實(shí)現(xiàn) IPC 呢?
主要是基于性能、穩(wěn)定性和安全性幾方面的原因。

優(yōu)勢(shì) 描述
性能 只需要一次數(shù)據(jù)拷貝,性能上僅次于共享內(nèi)存
穩(wěn)定性 基于 C/S 架構(gòu),職責(zé)明確、架構(gòu)清晰,因此穩(wěn)定性好
安全性 為每個(gè) APP 分配 UID,進(jìn)程的 UID 是鑒別進(jìn)程身份的重要標(biāo)志
Linux 下傳統(tǒng)的進(jìn)程間通信原理

了解 Linux IPC 相關(guān)的概念和原理有助于我們理解 Binder 通信原理。

基本概念介紹
image.png

上圖展示了 Liunx 中跨進(jìn)程通信涉及到的一些基本概念

  • 進(jìn)程隔離
  • 進(jìn)程空間劃分:用戶(hù)空間(User Space)/內(nèi)核空間(Kernel Space)
  • 系統(tǒng)調(diào)用:用戶(hù)態(tài)/內(nèi)核態(tài)

系統(tǒng)調(diào)用是用戶(hù)空間訪問(wèn)內(nèi)核空間的唯一方式,保證了所有的資源訪問(wèn)都是在內(nèi)核的控制下進(jìn)行的,避免了用戶(hù)程序?qū)ο到y(tǒng)資源的越權(quán)訪問(wèn),提升了系統(tǒng)安全性和穩(wěn)定性。

傳統(tǒng)的 IPC 通信方式有兩個(gè)問(wèn)題:

  • 性能低下,一次數(shù)據(jù)傳遞需要經(jīng)歷:內(nèi)存緩存區(qū) --> 內(nèi)核緩存區(qū) --> 內(nèi)存緩存區(qū),需要 2 次數(shù)據(jù)拷貝
  • 接收數(shù)據(jù)的緩存區(qū)由數(shù)據(jù)接收進(jìn)程提供,但是接收進(jìn)程并不知道需要多大的空間來(lái)存放將要傳遞過(guò)來(lái)的數(shù)據(jù),因此只能開(kāi)辟盡可能大的內(nèi)存空間或者先調(diào)用 API 接收消息頭來(lái)獲取消息體的大小,這兩種做法不是浪費(fèi)空間就是浪費(fèi)時(shí)間。
Binder 跨進(jìn)程通信原理

Binder 并不是 Linux 系統(tǒng)內(nèi)核的一部分,那怎么辦呢?這就得益于 Linux 的動(dòng)態(tài)內(nèi)核可加載模塊(Loadable Kernel Module,LKM)的機(jī)制;

在 Android 系統(tǒng)中,這個(gè)運(yùn)行在內(nèi)核空間,負(fù)責(zé)各個(gè)用戶(hù)進(jìn)程通過(guò) Binder 實(shí)現(xiàn)通信的內(nèi)核模塊就叫 Binder 驅(qū)動(dòng)(Binder Dirver)。

特性: 內(nèi)存映射。

內(nèi)存映射簡(jiǎn)單的講就是將用戶(hù)空間的一塊內(nèi)存區(qū)域映射到內(nèi)核空間。映射關(guān)系建立后,用戶(hù)對(duì)這塊內(nèi)存區(qū)域的修改可以直接反應(yīng)到內(nèi)核空間;反之內(nèi)核空間對(duì)這段區(qū)域的修改也能直接反應(yīng)到用戶(hù)空間。

Binder IPC 實(shí)現(xiàn)原理
IBinder通宵流程.png
  • 首先 Binder 驅(qū)動(dòng)在內(nèi)核空間創(chuàng)建一個(gè)數(shù)據(jù)接收緩存區(qū);
  • 接著在內(nèi)核空間開(kāi)辟一塊內(nèi)核緩存區(qū),建立內(nèi)核緩存區(qū)和內(nèi)核中數(shù)據(jù)接收緩存區(qū)之間的映射關(guān)系,以及內(nèi)核中數(shù)據(jù)接收緩存區(qū)和接收進(jìn)程用戶(hù)空間地址的映射關(guān)系;
  • 發(fā)送方進(jìn)程通過(guò)系統(tǒng)調(diào)用 copy_from_user() 將數(shù)據(jù) copy 到內(nèi)核中的內(nèi)核緩存區(qū),由于內(nèi)核緩存區(qū)和接收進(jìn)程的用戶(hù)空間存在內(nèi)存映射,因此也就相當(dāng)于把數(shù)據(jù)發(fā)送到了接收進(jìn)程的用戶(hù)空間,這樣便完成了一次進(jìn)程間的通信。
Binder 通信模型

一次完整的進(jìn)程間通信必然至少包含兩個(gè)進(jìn)程,通常我們稱(chēng)通信的雙方分別為客戶(hù)端進(jìn)程(Client)和服務(wù)端進(jìn)程(Server),由于進(jìn)程隔離機(jī)制的存在,通信雙方必然需要借助 Binder 來(lái)實(shí)現(xiàn)。

  • Binder 是基于 C/S 架構(gòu)的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder 驅(qū)動(dòng)。
  • 其中 Service Manager 和 Binder 驅(qū)動(dòng)由系統(tǒng)提供,而 Client、Server 由應(yīng)用程序來(lái)實(shí)現(xiàn)。
  • 其中 Client、Server、Service Manager 運(yùn)行在用戶(hù)空間,Binder 驅(qū)動(dòng)運(yùn)行在內(nèi)核空間。
  • Client、Server 和 ServiceManager 均是通過(guò)系統(tǒng)調(diào)用 open、mmap 和 ioctl 來(lái)訪問(wèn)設(shè)備文件 /dev/binder,從而實(shí)現(xiàn)與 Binder 驅(qū)動(dòng)的交互來(lái)間接的實(shí)現(xiàn)跨進(jìn)程通信。
  • Client、Server、ServiceManager、Binder 驅(qū)動(dòng)這幾個(gè)組件在通信過(guò)程中扮演的角色就如同互聯(lián)網(wǎng)中服務(wù)器(Server)、客戶(hù)端(Client)、DNS域名服務(wù)器(ServiceManager)以及路由器(Binder 驅(qū)動(dòng))之前的關(guān)系。
Binder 通信中的代理模式

假對(duì)象,真數(shù)據(jù)

A 進(jìn)程想要 B 進(jìn)程中某個(gè)對(duì)象(object)是如何實(shí)現(xiàn)的呢?畢竟它們分屬不同的進(jìn)程,A 進(jìn)程 沒(méi)法直接使用 B 進(jìn)程中的 object。

  • 驅(qū)動(dòng)并不會(huì)真的把 object 返回給 A,而是返回了一個(gè)跟 object 看起來(lái)一模一樣的代理對(duì)象 objectProxy;
  • 這個(gè) objectProxy 具有和 object 一摸一樣的方法,但是這些方法并沒(méi)有 B 進(jìn)程中 object 對(duì)象那些方法的能力,這些方法只需要把把請(qǐng)求參數(shù)交給驅(qū)動(dòng)即可。對(duì)于 A 進(jìn)程來(lái)說(shuō)和直接調(diào)用 object 中的方法是一樣的。
  • Binder 驅(qū)動(dòng)接收到 A 進(jìn)程的消息后,發(fā)現(xiàn)這是個(gè) objectProxy 就去查詢(xún)自己維護(hù)的表單,一查發(fā)現(xiàn)這是 B 進(jìn)程 object 的代理對(duì)象。于是就會(huì)去通知 B 進(jìn)程調(diào)用 object 的方法,并要求 B 進(jìn)程把返回結(jié)果發(fā)給自己。當(dāng)驅(qū)動(dòng)拿到 B 進(jìn)程的返回結(jié)果后就會(huì)轉(zhuǎn)發(fā)給 A 進(jìn)程,一次通信就完成了。
手動(dòng)編碼實(shí)現(xiàn)跨進(jìn)程調(diào)用

實(shí)現(xiàn)進(jìn)程間通信用的最多的就是 AIDL。
當(dāng)我們定義好 AIDL 文件,在編譯時(shí)編譯器會(huì)幫我們生成代碼實(shí)現(xiàn) IPC 通信。
借助 AIDL 編譯以后的代碼能幫助我們進(jìn)一步理解 Binder IPC 的通信原理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容