一丶Android多進程通信的應(yīng)用場景?
- 保活
- webview
- 加載圖片
- push推送
- 與系統(tǒng)服務(wù)通信
二丶為什么要用binder
- Android系統(tǒng)內(nèi)核是linux內(nèi)核
- Linux內(nèi)核進程通信有:管道、內(nèi)存共享、Socket、File;
- 對比:

Binder的一次拷貝發(fā)生在用戶空間拷貝到內(nèi)核空間;
用戶空間: App進程運行的內(nèi)存空間;
內(nèi)核空間: 系統(tǒng)驅(qū)動、和硬件相關(guān)的代碼運行的內(nèi)存空間,也就是進程ID為0的進程運行的空間;
程序局部性原則: 只加載少量代碼;應(yīng)用沒有運行的代碼放在磁盤中,運行時高速緩沖區(qū)進行加載要運行的代碼;默認一次加載一個頁(4K),若不夠4K就用0補齊;
MMU:內(nèi)存管理單元;
給CPU提供虛擬地址;
當對變量操作賦值時:
- CPU拿著虛擬地址和值給到MMU
- MMU用虛擬地址匹配到物理地址,MMU去物理內(nèi)存中進行賦值;
物理地址: 物理內(nèi)存的實際地址,并不是磁盤;
虛擬地址: MMU根據(jù)物理內(nèi)存的實際地址翻譯出的虛擬地址;提供給CPU使用;


頁命中:CPU讀取變量時,MMU在物理內(nèi)存的頁表中找到了這個地址;
頁未命中:CPU讀取變量時,MMU在物理內(nèi)存的頁表中沒有找到了這個地址,此時會觸發(fā)MMU去磁盤讀取變量并存到物理內(nèi)存中;
普通的二次拷貝:
應(yīng)用A拷貝到服務(wù)端:coay_from_user
從服務(wù)端拷貝到應(yīng)用B:coay_to_user
mmap():
- 在物理內(nèi)存中開辟一段固定大小的內(nèi)存空間
- 將磁盤文件與物理內(nèi)存進行映射(理解為綁定)
- MMU將物理內(nèi)存地址轉(zhuǎn)換為虛擬地址給到CPU(虛擬地址映射物理內(nèi)存)
共享內(nèi)存進程通信:
- 進程A調(diào)用mmap()函數(shù)會在內(nèi)核空間中虛擬地址和一塊同樣大小的物理內(nèi)存,將兩者進行映射
- 得到一個虛擬地址
- 進程B調(diào)用mmap()函數(shù),傳參和步驟1一樣的話,就會得到一個和步驟2相同的虛擬地址
- 進程A和進程B都可以用同一虛擬地址對同一塊映射內(nèi)存進行操作
- 進程A和進程B就實現(xiàn)了通信
- 沒有發(fā)生拷貝,共享一塊內(nèi)存,不安全
Binder通信原理:
角色:Server端A、Client端B、Binder驅(qū)動、內(nèi)核空間、物理內(nèi)存
- Binder驅(qū)動在物理內(nèi)存中開辟一塊固定大小(1M-8K)的物理內(nèi)存w,與內(nèi)核空間的虛擬地址x進行映射得到
- A的用戶空間的虛擬地址ax和物理內(nèi)存w進行映射
- 此時內(nèi)核空間虛擬地址x和物理內(nèi)存w已經(jīng)進行了映射,物理內(nèi)存w和Server端A的用戶空間虛擬地址ax進行了映射:也就是 內(nèi)核空間的虛擬地址x = 物理內(nèi)存w = Server端A的用戶空間虛擬地址ax
- B發(fā)送請求:將數(shù)據(jù)按照binder協(xié)議進行打包給到Binder驅(qū)動,Binder驅(qū)動調(diào)用coay_from_user()將數(shù)據(jù)拷貝到內(nèi)核空間的虛擬地址x
- 因步驟3中的三塊區(qū)域進行了映射
- Server端A就得到了Client端B發(fā)送的數(shù)據(jù)
- 通過內(nèi)存映射關(guān)系,只發(fā)生了一次拷貝

Activity跳轉(zhuǎn)時,最多攜帶1M-8k(1兆減去8K)的數(shù)據(jù)量;
真實數(shù)據(jù)大小為:1M內(nèi)存-兩頁的請求頭數(shù)據(jù)=1M-8K;
應(yīng)用A直接將數(shù)據(jù)拷貝到應(yīng)用B的物理內(nèi)存空間中,數(shù)據(jù)量不能超過1M-8K;拷貝次數(shù)少了一次,少了從服務(wù)端拷貝到用戶;
IPC通信機制:
- 服務(wù)注冊
- 服務(wù)發(fā)現(xiàn)
- 服務(wù)調(diào)用
以下為簡單的主進程和子進程通信:
1、服務(wù)注冊: 緩存中心中有三張表(暫時理解為三個HashMap,Binder用的是native的紅黑樹):
- 第一種:放key :String - value:類的Class;
- 第二種:放key :Class的類名 - value:類的方法集合;
- 第三種:放key :Class的類名 - value:類的對象;
類的方法集合:key-value;
key:方法簽名:“方法名” 有參數(shù)時用 “方法名-參數(shù)類型-參數(shù)類型-參數(shù)類型......”;
value: 方法本身;
注冊后,服務(wù)若沒被調(diào)用則一直處于沉默狀態(tài),不會占用內(nèi)存,這種情況只是指用戶進程里自己創(chuàng)建的服務(wù),不適用于AMS這種;
2、服務(wù)發(fā)現(xiàn): 當被查詢到時,要被初始化;
- 客戶端B通過發(fā)送信息到服務(wù)端A
- 服務(wù)端解析消息,反序列化
- 通過反射得到消息里的類名,方法,從注冊時的第一種、第二種表里找到Class,若對象沒初始化則初始化對象,并將對象添加到第三種的表里;
3、服務(wù)調(diào)用:
- 使用了動態(tài)代理
- 客戶端在服務(wù)發(fā)現(xiàn)時,拿到對象(其實是代理)
- 客戶端調(diào)用對象方法
- 代理發(fā)送序列化數(shù)據(jù)到服務(wù)端A
- 服務(wù)端A解析消息,反序列化,得到方法進行處理,得到序列化數(shù)據(jù)結(jié)果
- 將序列化結(jié)果寫入到客戶端進程的容器中;
- 回調(diào)給客戶端
AIDL: BpBinder:數(shù)據(jù)發(fā)送角色 BbBinder:數(shù)據(jù)接收角色

編譯器生成的AIDL的JAVA接口.Stub.proxy.transact()為數(shù)據(jù)發(fā)送處;
發(fā)送的數(shù)據(jù)包含:數(shù)據(jù)+方法code+方法參數(shù)等等;
- 發(fā)送時調(diào)用了Linux的驅(qū)動
- 調(diào)用copy_from_user()拷貝用戶發(fā)送的數(shù)據(jù)到內(nèi)核空間
- 拷貝成功后又進行了一次請求頭的拷貝:copy_from_user()
- 也就是把一次的數(shù)據(jù)分為兩次拷貝
請求頭:包含了目的進程、大小等等參數(shù),這些參數(shù)占了8K
編譯器生成的AIDL的java接口.Stub.onTransact()為數(shù)據(jù)接收處;
Binder中的IPC機制:
- 每個App進程啟動時會在內(nèi)核空間中映射一塊1M-8K的內(nèi)存
- 服務(wù)端A的服務(wù)注冊到ServiceManager中:服務(wù)注冊
- 客戶端B想要調(diào)用服務(wù)端A的服務(wù),就去請求ServiceManager
- ServiceManager去讓服務(wù)端A實例化服務(wù):服務(wù)發(fā)現(xiàn)
- 返回一個用來發(fā)送數(shù)據(jù)的對象BpBinder給到客戶端B
- 客戶端B通過BpBinder發(fā)送數(shù)據(jù)到服務(wù)端A的內(nèi)核的映射區(qū)域(傳參時客戶端會傳一個reply序列化對象,在底層會將這個地址一層一層往下傳,直至傳到回調(diào)客戶端):這里發(fā)生了一次通信copy_from_user:服務(wù)調(diào)用
- 服務(wù)端A通過BBBinder得到數(shù)據(jù)并處理數(shù)據(jù)
- 服務(wù)端喚醒客戶端等待的線程;將返回結(jié)果寫入到客戶端發(fā)送請求時傳的一個reply容器地址中,調(diào)用onTransact返回;
- 客戶端在onTransac中得到數(shù)據(jù);通信結(jié)束;
ServiceManager維持了Binder這套通信框架;
三丶APP多進程的優(yōu)點
- 擴大應(yīng)用可使用的內(nèi)存
手機內(nèi)存6G,系統(tǒng)分配給虛擬機的內(nèi)存一般32M、48M、64M,使用多進程時,可以使用一個進程專門加載圖片,防止OOM。 - 子進程崩潰,不會導(dǎo)致主進程崩潰
- 互相保活,即如果子進程被系統(tǒng)kill掉時,主進程拉起子進程。主進程被系統(tǒng)kill掉時,子進程拉起主進程。
四丶多進程通信原理

Android進程是運行在系統(tǒng)分配的虛擬地址空間,虛擬地址空間分為用戶空間和內(nèi)核空間。多進程間,用戶空間不共享,內(nèi)核空間共享,進程間通過共享的內(nèi)核空間通信。
五丶多進程通信有哪些方式?
1.傳統(tǒng)的IPC方式:socket,內(nèi)存共享。
2.Android特有的方式:Binder。
六丶Binder相對其他IPC方式優(yōu)點/為什么使用Binder?

1.性能:
A.Socket傳輸數(shù)據(jù)的過程:兩次拷貝

B.Binder傳輸數(shù)據(jù)的過程:一次拷貝

內(nèi)存映射:MMAP(memory map)
虛擬內(nèi)存和物理內(nèi)存
虛擬內(nèi)存映射到物理內(nèi)存,物理內(nèi)存存儲數(shù)據(jù)。
2.易用性
3.安全性
七丶Binder在Android系統(tǒng)CS通信機制中起到的作用
- Android C/S通信機制
- Binder機制的關(guān)鍵概念
- Binder在Android CS通信機制中起到的作用
AIDL和Binder的關(guān)系?
AIDL封裝了Binder,AIDL調(diào)用Binder