Android Binder 的996.icu

1、主要內容

Binder在Android中有舉足輕重的地位,不論是Activty的啓動流程,仍是四大組件的通信方式都一一和binder有着細密的關聯。 主要從四個大方向介紹Binder:

  • Binder由來和特性:首先是對Binder有個完整的認識和他存在的優點分析
  • Linux下IPC原理:Android是基於Linux的,因此先了解下Linux固有的進程通信的方式有助於對Binder的理解
  • Binder原理:主要包括組件的構成、架構和通信原理
  • Binder有關的常見問題:一些常見的和不常見的有關Binder的問題有助於更好的理解和加深對Binder的認識

2、Binder概述

1.什麼是Binder?

  • 從IPC角度來講:Binder是Android中的一種跨進程通訊方式,該通訊方式在linux中沒有,是Android獨有;
  • 從Android Driver層:Binder還能夠理解爲一種虛擬的物理設備,它的設備驅動是/dev/binder;
  • 從Android Native層:Binder是建立Service Manager以及BpBinder/BBinder模型,搭建與binder驅動的橋樑;
  • 從Android Framework層:Binder是各類Manager(ActivityManager、WindowManager等)和相應xxxManagerService的橋樑;
  • 從Android APP層:Binder是客戶端和服務端進行通訊的媒介,當bindService的時候,服務端會返回一個包含了服務端業務調用的 Binder對象,經過這個Binder對象,客戶端就能夠獲取服務端提供的服務或者數據,這裏的服務包括普通服務和基於AIDL的服務。

2.由來?

Android 系統是基於 Linux 內核的,Linux 已經提供了管道、消息隊列、共享內存和 Socket 等 IPC 機制。那爲何 Android 還要提供 Binder 來實現 IPC 呢?主要是基於性能、穩定性和安全性幾方面的緣由。linux

  • 管道:任何進程都能通信,但速度慢
  • 消息隊列:容量受到系統限制,且要注意第一次讀的時候,要考慮上一次沒有讀完數據的問題。
  • 共享內存:可以容易控制容量,速度快,但要保持同步,好比寫一個進程的時候,另外一個進程要注意讀寫的問題,至關於線程中的線程安全。固然,共享內存一樣能夠做爲線程通信,不過沒有這個必要,線程間原本就已經共享了同一個進程內的一塊內存。
  • socket:本機進程之間能夠利用socket通訊,跨進程之間也可利用socket通訊,一般RPC的實現最底層都是經過socket通訊。socket通訊是一種比較複雜的通訊方式,一般客戶端須要開啓單獨的監聽線程來接受從服務端發過來的數據,客戶端線程發送數據給服務端,若是須要等待服務端的響應,並經過監聽線程接受數據,須要進行同步,是一件很麻煩的事情。socket通訊速度也不快。

3.Binder特性?

3.1 性能?

  • 共享內存雖然無需拷貝,但控制複雜,難以使用。
  • Binder 只須要一次數據拷貝,性能上僅次於共享內存。
  • Socket 做爲一款通用接口,其傳輸效率低,開銷大,主要用在跨網絡的進程間通訊和本機上進程間的低速通訊。
  • 消息隊列和管道採用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開闢的緩存區中,而後再從內核緩存區拷貝到接收方緩存區,至少有兩次拷貝過程。

3.2 穩定性?

  • Binder 基於 C/S 架構,客戶端(Client)有什麼需求就丟給服務端(Server)去完成,架構清晰、職責明確又相互獨立,天然穩定性更好。
  • 共享內存雖然無需拷貝,可是控制負責,難以使用。從穩定性的角度講,Binder 機制是優於內存共享的。

3.3 安全性?

  • 首先傳統的 IPC 接收方沒法得到對方可靠的進程用戶ID/進程ID(UID/PID),從而沒法鑑別對方身份。
  • Android 爲每一個安裝好的 APP 分配了本身的 UID,故而進程的 UID 是鑑別進程身份的重要標誌。傳統的 IPC 只能由用戶在數據包中填入 UID/PID,但這樣不可靠,容易被惡意程序利用。可靠的身份標識只有由 IPC 機制在內核中添加。其次傳統的 IPC訪問接入點是開放的,只要知道這些接入點的程序均可以和對端創建鏈接,無論怎樣都沒法阻止惡意程序經過猜想接收方地址得到鏈接。
  • 同時 Binder 既支持實名 Binder,又支持匿名 Binder,安全性高(Binder.getCallingUid())。

3.4 結論:

3、Linux下IPC原理

1.進程隔離

  • 進程與進程間內存是不共享的。兩個進程就像兩個平行的世界,A 進程無法直接訪問 B 進程的數據,這就是進程隔離的通俗解釋。
  • A 進程和 B 進程之間要進行數據交互就得采用特殊的通訊機制:進程間通訊(IPC)。

2.用戶空間與內核空間

  • 每一個Android的進程,只能運行在本身進程所擁有的虛擬地址空間。對應一個4GB的虛擬地址空間,其中3GB是用戶空間,1GB是內核空間,固然內核空間的大小是能夠經過參數配置調整的。對於用戶空間,不一樣進程之間彼此是不能共享的,而內核空間倒是可共享的。
  • 簡單的說就是,內核空間(Kernel)是系統內核運行的空間,用戶空間(User Space)是用戶程序運行的空間。爲了保證安全性,它們之間是隔離的。

3.用戶態與內核態

  • 雖然從邏輯上抽離出用戶空間和內核空間;可是不可避免的的是,總有那麼一些用戶空間須要訪問內核的資源;好比應用程序訪問文件,網絡是很常見的事情,怎麼辦呢?面試

  • 當一個任務(進程)執行系統調用而陷入內核代碼中執行時,咱們就稱進程處於內核運行態(內核態)此時處理器處於特權級最高的(0級)內核代碼中執行。當進程在執行用戶本身的代碼時,則稱其處於用戶運行態(用戶態)。即此時處理器在特權級最低的(3級)用戶代碼中運行。處理器在特權等級高的時候才能執行那些特權CPU指令。緩存

  • 系統調用主要經過以下兩個函數來實現:安全

copy_from_user() //將數據從用戶空間拷貝到內核空間
    copy_to_user() //將數據從內核空間拷貝到用戶空間
複製代碼

4、Binder原理

4.1 Binder組成

Binder 是基於 C/S 架構的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder 驅動。其中 Client、Server、Service Manager 運行在用戶空間,Binder 驅動運行在內核空間。其中 Service Manager 和 Binder 驅動由系統提供,而 Client、Server 由應用程序來實現。Client、Server 和 ServiceManager 均是經過系統調用 open、mmap 和 ioctl 來訪問設備文件 /dev/binder,從而實現與 Binder 驅動的交互來間接的實現跨進程通訊。

  • Clientbash

    如同互聯網中客戶端(Client),Binder是Server本地對象的一個引用,這個引用其實是一個代理對象,Client經過這個代理對象來間接訪問Server的本地對象;服務器

  • Server網絡

    如同互聯網中服務器(Server),Binder是提供具體實現的本地對象,需向ServiceManager註冊;架構

  • ServiceManagersocket

    如同互聯網中DNS域名服務器(ServiceManager),管理Servive註冊和查詢,做用是將字符形式的 Binder 名字轉化成 Client 中對該 Binder 的引用,使得 Client 可以經過 Binder 的名字得到對 Binder 實體的引用。註冊了名字的 Binder 叫實名 Binder,就像網站同樣除了除了有 IP 地址意外還有本身的網址。函數

  • 驅動

    如同互聯網中路由器(Binder 驅動),是整個通訊的核心;驅動負責進程之間 Binder 通訊的創建,Binder 在進程之間的傳遞,Binder 引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。

4.2 Binder架構

Binder架構採用分層架構設計,每一層都有其不一樣的功能,以你們平時用的startService爲例子,AMP爲ActivityManagerProxy,AMS爲ActivityManagerSerivce。BpBinder是Client端建立的用於向Server發送消息的代理,而BBinder是Server端用於接受消息的通道。

  • Binder 通訊採用 C/S 架構,從組件視角來講,包含 Client、 Server、 ServiceManager 以及 Binder 驅動,其中 ServiceManager 用於管理系統中的各類服務。
  • Binder 在 framework 層進行了封裝,經過 JNI 技術調用 Native(C/C++)層的 Binder 架構。
  • Native 層: 對於Native層,若是須要使用Binder,則能夠直接使用BpBinder和BBinder(也包括JavaBBindder)便可,對於上一層Java IPC通訊也是基於這個層面。
  • Kernel物理層:這裏是Binder Driver,前面三層都跑在用戶控件,對於用戶控件內存資源是不共享的,每一個Android的進程只能運行在本身基礎訥航所擁有的虛擬地址空間,而內核空間倒是可共享的。真正通訊的核心環節仍是Binder Driver。

4.3 Binder機制通信原理

  • Server向ServiceManager註冊Server經過Binder驅動向ServiceManager註冊,聲明能夠對外提供服務。ServiceManager中會保留一份映射表。
  • Client向ServiceManager請求Server的Binder查詢Client想要請求Server的數據時,須要先經過Binder驅動向ServiceManager請求Server的Binder引用:我要向名字爲zhangsan的Server通訊,請告訴我Server的Binder引用。
  • 向具體的Server發送請求Client拿到這個Binder引用後,就能夠經過Binder驅動和Server進行通訊了。
  • Server返回結果Server響應請求後,須要再次經過Binder驅動將結果返回給Client。

4.4 總結

  • 從進程間通訊的角度看,Binder 是一種進程間通訊的機制;
  • 從 Server 進程的角度看,Binder 指的是 Server 中的 Binder 實體對象;
  • 從 Client 進程的角度看,Binder 指的是對 Binder 代理對象,是 Binder 實體對象的一個遠程代理
  • 從傳輸過程的角度看,Binder 是一個能夠跨進程傳輸的對象;Binder 驅動會對這個跨越進程邊界的對象對一點點特殊處理,自動完成代理對象和本地對象之間的轉換。

5、Binder有關問題

相關文章
相關標籤/搜索