Android Binder開卷

一、IPC介紹

IPC全名爲inter-Process Communication,含義爲進程間通信,是指兩個進程之間進行數據交換的過程。

1.1爲什麼需要使用IPC?

內核空間和用戶空間

在操作系統中存在用戶空間(User space)和內核空間(Kernel space)。

Liunx採用虛擬內存管理技術,每一個進程都都有各自獨立的進程地址空間(以32位系統爲例,空間爲4G大小的線性虛擬空間),無法直接訪問物理內存。這樣避免了進程直接操作系統內核,保證系統安全,並且讓用戶程序可使用比實際物理內存更大的地址空間。

  • 4G進程地址被劃分爲兩部分,內核空間和用戶空間。用戶空間從0到3G,內核空間從3G到4G;
  • 用戶進程通常情況下只能訪問用戶空間的虛擬地址,不能訪問內核空間虛擬地址。只有用戶進程進行系統調用(代表用戶進程在內核態執行任務)等情況可訪問到內核空間;
  • 用戶內核對應進程,所以當進程切換,用戶空間也會跟着變化;
  • 內核空間是由內核負責映射,不會跟着進程變化;內核空間地址有自己對應的頁表,用戶進程有不同額頁表。
  • 所有進程的內核空間都是共享的,屬於所有進程,內核空間的數據是可以進程間共享的,而用戶空間則不可以。

進程隔離

進程隔離指的是,一個進程不能直接操作或者訪問另外一個進程,也就是進程A不可以直接訪問B的數據。

系統調用

用戶空間需要訪問內核空間,就需要藉助系統來實現。系統調用是用戶空間訪問內核空間的唯一方式,保證了所有的資源訪問都是在內核的控制下進行的,避免了用戶進程對系統資源的越權訪問,提升了系統的安全性和穩定性。

進程A和進程B的用戶空間可以通過如下系統函數和內核空間進行交互。

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

內存映射

由於應用程序不能直接操作設備設備硬件地址,所以操作系統提供了一種機制:內存映射,把設備地址映射到進程虛擬內存區。

內存映射全名爲Memory Map,在Liunx中通過系統調用函數mmap來實現內存映射。將用戶空間的一塊內存區域映射到內核空阿金。映射關係建立後,用戶對這塊內存的區域的修改可以直接反應到內核空間,反之亦然。內存映射能減少數據拷貝次數,實現用戶空間和內核空間的高效互動。

二、Liunx的IPC通信原理

內核程序在內核空間分配內存並開闢一塊內核緩存區,發送進程通過copy_from_user函數將數據拷貝到內核空空間的緩衝區中。同樣,接收進程在接收數據時再自己的用戶空間開闢一塊內存緩存區,然後內核程序調用copy_to_user() 函數將數據從內核緩存區拷貝到接收進程。這樣數據發送進程和數據接收進程完成了一次數據傳輸,也就是一次進程間通信。

Linux的IPC通信原理有兩個問題:

  1. 一次數據傳遞需要經歷:用戶空間 –> 內核緩存區 –> 用戶空間,需要2次數據拷貝,這樣效率不高。
  2. 接收數據的緩存區由數據接收進程提供,但是接收進程並不知道需要多大的空間來存放將要傳遞過來的數據,因此只能開闢儘可能大的內存空間或者先調用API接收消息頭來獲取消息體的大小,浪費了空間或者時間。

2.1 Liunx中的IPC機制種類

  1. 管道(pipe)是Liunx有Unix那裏繼承過來的進程間通信機制。原理是在內存中創建一個共享文件,從而使通信雙方利用這個共享文件來傳遞信息。這個共享文件比較特殊,它不屬於文件系統並且只存在於內存中。另外,管道採用的是半雙工通信方式,數據只能在一個方向上流動。
    簡單的模型如下所示。

2、信號

信號是軟件層次上對中斷機制的一種模擬,是一種異步通信方式,進程不必通過任何操作來等待信號的到達。信號可以在用戶空間進程和內核之間直接交互,內核可以利用信號來通知用戶空間的進程發生了哪些系統事件。信號不適用於信息交換,比較適用於進程中斷控制。

3、信號量

信號量是一個計數器,用來控制多個進程對共享資源的訪問。它常用來作爲一種鎖機制,防止某種進程正在訪問共享資源時,其他進程也訪問該資源。主要作爲進程間以及同意進程內不同線程之間的同步手段。

4、消息隊列

消息隊列時消息的鏈表,具有特定的格式,存放在內存中並由消息隊列標識符標識,並且允許一個或多個進程向它寫入與讀取消息。信息會複製兩次,因此對於頻繁或者信息量大的通信不宜使用消息隊列。

5、共享內存

多個進程可以直接讀寫的一塊內存空間,是針對其他通信機制運行效率太低而設計的。爲了在多個進程間交換信息,內核專門留出了一塊內存區,可以由需要訪問的進程映射到自己大的私有地址空間。進程就可以直接讀寫這一塊內存而不需要進行數據的拷貝,從而大大的提高效率。

6、套接字

套接字是更爲基礎的進程間通信機制,與其他方式不同的是,套接字可用於不同機器之間的進程間通信。

2、2Android中的IPC機制

Android系統是基於Linux內核的,在Liunx內核基礎上又擴展出了一些IPC機制。Android系統除了支持套接字,還支持序列化、Messenger、AIDL、Bundle、文件共享、ContentProvider、Binder等。

1、序列化

序列化指的是Serializable/Parcelable,Serializable是java提供的一個序列化接口,是一個空接口,爲對象提供標準的序列化和反序列化操作。Parcelable接口時Android中序列化方式。

2、Messenger

Messagner對象可以在不同進程中傳遞,在Message中加入我們想要傳的數據就可以在進程間進行數據傳遞了。Messagner是一種輕量級的IPC方案並對AIDL進行了封裝。

3、AIDL

AIDL全名爲Android interface definition Language,即Android接口定義語言。Messenger是以串口的方式來處理客戶端發來的信息,如果又大量的消息發到服務端,服務端仍然一個一個處理再響應客戶端顯然是不適合的。另外還有一點,Messenger用來進程間進行數據傳遞但是不能滿足跨進程的方法調用,這個時候需要使用AIDL了。

4、Bundle
Bundle實現了Parcelable接口,所以它可以方便的在不同的進程間傳輸。Acitivity、Service、Receiver都是在Intent中通過Bundle來進行數據傳遞。

5、文件共享
兩個進程通過讀寫同一個文件來進行數據共享,共享的文件可以是文本、XML、JOSN。文件共享適用於對數據同步要求不高的進程間通信。

6、ContentProvider
ContentProvider爲存儲和獲取數據了提供統一的接口,它可以在不同的應用程序之間共享數據,本身就是適合進程間通信的。ContentProvider底層實現也是Binder,但是使用起來比AIDL要容易許多。系統中很多操作都採用了ContentProvider,例如通訊錄,音視頻等,這些操作本身就是跨進程進行通信。

參考文檔:

Android Binder原理

Binder系列

深入理解Android卷1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章