Android 圖文詳解Binder進程通信底層原理

之前瞭解到進程與多進程,涉及多進程不可避免的遇到瞭進程間通信,說到進程間通信,Binder 成瞭一道繞不過的坎。接下來咱們逐一瞭解。

🔥 什麼是進程間通信

進程間通信(IPC,Inner Process Comunication),就是指不同進程之間的信息傳遞。

進程是系統進行資源分配和調度的基本單位,是操作系統的結構的基礎;一個應用至少有一個進程,一個進程中有包含瞭多個線程(線程是CPU調度的最小單位),進程相當於是線程的ViewGroup,線程相當於操作系統分配個進程的View。

🔥 什麼是 Binder

Binder 是 Android 系統中進程間通信機制(IPC)的一種方式,它是這些進程間通訊的橋梁。正如其名”粘合劑”一樣,它把系統中各個組件粘合到瞭一起,是各個組件的橋梁。

應用層:是一個能發起通信的Java類。

  • Client:是對 Binder 代理對象,是 Binder 實體對象的一個遠程代理。
  • Server:是 Server 中的 Binder 實體對象。

機制:是一種進程間通信機制。

驅動:是一個虛擬物理設備驅動;

如startActivity的簡圖:

這裡就用到瞭 Binder 通信,你會發現這裡還有 Socker 通信,那我為什麼要用 Binder 而不用 Socket。

🔥 Android 中 IPC 的方式

名稱 特點 使用場景
Bundle 隻能傳輸實現瞭序列化或者一些Android支持的特殊對象 適合用於四大組件之間的進程交互
文件 不能做到進程間的即時通信,並且不適合用於高並發的場景 適合用於SharedPreference以及IO操作
ContentProvider 可以訪問較多的數據,支持一對多的高並發訪問,因為ContentProvider已經自動做好瞭關於並發的機制 適合用於一對多的數據共享並且需要對數據進行頻繁的CRUD操作
Socket 通過網絡傳輸字節流,支持一對多的實時通信,但是實現起來比較復雜 適合用於網絡數據共享
Messenger 底層原理是AIDL,隻是對其做瞭封裝,但是不能很好的處理高並發的場景,並且傳輸的數據隻能支持Bundle類型 多進程、單線程且線程安全
AIDL 功能強大,使用Binder機制,支持一對多的高並發實時通信,但是需要處理好線程同步 一對多並且有遠程進程通信的場景

🔥 Binder 優勢

出發點 Binder 共享內存 Socket
性能 拷貝一次 無需拷貝 拷貝兩次
特點 基於C/S架構,易用性高 控制復雜,易用性差 基於C/S架構,通用接口,傳輸效率低、開銷大
安全 每個APP分配UID,同時支持實名和匿名 依賴上層協議,訪問接入點是開放的不安全 依賴上層協議,訪問接入點是開放的不安全

通過以上對比,Android 最終選擇瞭自建一套兼顧好用、高效、安全的 Binder。

  • 好用:基於C/S架構,易用性高
  • 高效:用 mmap() 進行內存映射,隻需一次拷貝
  • 安全強:每個 APP 分配UID(進程的身份證號),同時支持實名(系統服務)和匿名(自己創建的服務)

可以讓自己的服務前往 ServiceManager 註冊,註冊後實名。

🔥 Linux 傳統的 IPC 原理

瞭解 Linux IPC 相關的概念和原理有助於我們理解 Binder 通信原理。因此,在介紹 Binder 跨進程通信原理之前,我們先聊聊 Linux 系統下傳統的進程間通信是如何實現。

💥 基本概念

由上圖看出:

  • 進程隔離。
  • 進程空間劃分:用戶空間(User Space)/內核空間(Kernel Space)。
  • 系統調用:用戶態/內核態。

🌀 進程隔離

操作系統中,進程與進程間內存是不共享的。SCC 進程無法直接訪問 Service 進程的數據。SCC 進程和 Service 進程之間要進行數據交互就得采用進程間通信(IPC)。

🌀 進程空間劃分

現在操作系統都是采用的虛擬存儲器。操作系統的核心是內核,獨立於普通的應用程序,可以訪問受保護的內存空間,也可以訪問底層硬件設備的權限。為瞭保護用戶進程不能直接操作內核,保證內核的安全,操作系統從邏輯上將虛擬空間劃分為用戶空間(User Space)和內核空間(Kernel Space)。

內核空間(Kernel Space):是系統內核運行的空間;

用戶空間(User Space):是用戶程序運行的空間。

所有內核空間(虛擬地址)都映射在同一塊物理內存,這樣就實現瞭內存共享(所有進程可通過IPC訪問)。

為瞭保證安全性,它們之間是隔離的。即使用戶程序蹦瞭,內核也不受影響。

🌀 系統調用

進程內 用戶空間 & 內核空間 進行交互 需通過系統調用,主要通過函數:

copy_from_user():將用戶空間的數據拷貝到內核空間;

copy_to_user():將內核空間的數據拷貝到用戶空間。

用戶態:當進程在執行用戶自己的代碼的時候,我們稱其處於用戶運行態(用戶態);

內核態:當一個進程執行系統調用而陷入內核代碼中執行時,稱進程處於內核運行態(內核態)。

系統調用是用戶空間訪問內核空間的唯一方式。

💥 傳統 IPC 通信原理

如圖,這就是 Sokcet的拷貝兩次。

當然目前 Linux 已經引入 Binder 通信機制。

🔥 Binder IPC原理

上面整瞭一堆 Linux 下的 IPC 相關概念及原理,接下來我們正式介紹下 Binder IPC 的原理。

💥 Binder 采用分層架構設計

  • 應用層: 對於應用通過調用startActivity()然後調用 AMP.startService , 經過層層調用,最終必然會調用到AMS.startService。
  • Framework: 客戶類BinderProxy和服務類Binder(Binder通信是采用C/S架構, Android系統的基礎架構便已設計好Binder在Java )。
  • Native層: 對於Native層,可以直接使用BpBinder和BBinder(當然這裡還有JavaBBinder)即可, 對於上一層Framework 的通信也是基於這個層面。
  • Kernel: 這裡是Binder Driver, 前面3層都跑在用戶空間,對於用戶空間的內存資源是不共享的,每個Android的進程隻能運行在自己進程所擁有的虛擬地址空間, 而內核空間卻是可共享的. 真正通信的核心環節還是在Binder Driver。

💥 Binder 驅動

在 Android 系統中,這個運行在內核空間,負責各個用戶進程通過 Binder 實現通信的內核模塊就叫 Binder 驅動(Binder Dirver)。

💥 Binder IPC 內存映射

Binder IPC 正是基於內存映射(mmap)來實現的,一次完整的 Binder IPC 通信過程通常是這樣:

1、Binder 驅動在內核空間創建一個數據接收緩存區;

2、在內核空間開辟一塊內核緩存區,

  • 建立內核緩存區和內核中數據接收緩存區之間的映射關系;
  • 內核中數據接收緩存區和接收進程用戶空間地址的映射關系;

3、發送數據完成瞭一次進程間的通信。

  • 發送方進程通過系統調用 copy_from_user() 將數據 拷貝 到內核中的內核緩存區;
  • 由於內核緩存區和數據接收緩存區存在內存映射,因此也就相當於把數據發送到瞭數據接收緩存區;
  • 由於數據接收緩存區和進程的用戶空間存在內存映射因此也就相當於把數據發送到瞭接收進程的用戶空間。

內存映射能減少數據拷貝次數,實現用戶空間和內核空間的高效互動。兩個空間各自的修改能直接反映在映射的內存區域,從而被對方空間及時感知。也正因為如此,內存映射能夠提供對進程間通信的支持。

Binder傳值限制:

  • 原來的 BINDER_VM_SIZE:((1 * 1024 * 1024) - 4096 * 2)
  • 現在的BINDER_VM_SIZE:((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

sysconf(_SC_PAGE_SIZE):這個函數用來獲取系統執行的配置信息。例如頁大小、最大頁數、cpu個數、打開句柄的最大個數等等。

這個值表示你Binder最多傳這麼多,超出就失敗。

💥 Android Binder 原理圖

🌀 Bind 原理圖

Binder通信采用C/S架構,從組件視角來說,包含Client、Server、ServiceManager 以及 Binder 驅動,其中 ServiceManager 用於管理系統中的各種服務。

此處的ServiceManager是指Native層的ServiceManager(C++),並非指framework層的ServiceManager(Java) 原因:

所以,原理圖可表示為以下:

🌀 Bind 原理圖交互

Client、Server、ServiceManager屬於進程空間的用戶空間,不可進行進程間交互(下圖虛線表示)。

所以他們都通過與 Binder 驅動 進行交互的,從而實現IPC通信方式。

所以,原理圖可表示為以下:

🌀 Bind 原理圖交互路線

到這裡 Binder 原理算是搞定瞭。不知道你懂瞭多少,有疑問可以聯系我,我們一起探討。下一篇咱們一起學習 Binder 在 Android 中的具體實現。

到此這篇關於Android 圖文詳解Binder進程通信底層原理的文章就介紹到這瞭,更多相關Android Binder內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: