AIDL使用以及IPC原理分析(進程間通信) 概要 為了大家能夠更好的理解android的進程間通信原理,以下將會從以下幾個方面講解跨進程通訊信: 1. 必要瞭解的概念 2. 為什麼要使用aidl進程間通信 3. 可能遇到的問題以及解決辦法 4. aidl的使用,通過android提供的aidl實現 ...
AIDL使用以及IPC原理分析(進程間通信)
概要
為了大家能夠更好的理解android的進程間通信原理,以下將會從以下幾個方面講解跨進程通訊信:
1. 必要瞭解的概念
2. 為什麼要使用aidl進程間通信
3. 可能遇到的問題以及解決辦法
4. aidl的使用,通過android提供的aidl實現一個進程間通信
5. 不使用aidl,手動編寫Binder實現進程間通信
6. 分析aidl的原理,梳理andriod進程間通信相關知識
我們從Android對aidl文件自動生成的java類中可以看到asInterface()這個介面的實現,大概的意思就是:
如果客戶端和服務端在同一個進程下,那麼asInterface()將返回Stub對象本身,否則返回Stub.Proxy對象。
也就是說asInterface()返回的對象有兩種可能(實際上有三種,還有一種是null),Stub和Stub.Proxy。它們有什麼區別呢?
如果在同一個進程下的話,那麼asInterface()將返回服務端的Stub對象本身,因為此時根本不需要跨進稱通信,那麼直接調用Stub對象的介面就可以了,返回的實現就是服務端的Stub實現,也就是根本沒有跨進程通信;
如果不是同一個進程,那麼asInterface()返回是Stub.Proxy對象,該對象持有著遠程的Binder引用,因為現在需要跨進程通信,所以如果調用Stub.Proxy的介面的話,那麼它們都將是IPC調用,它會通過調用transact方法去與服務端通信。
以上就是兩者的區別。
在android系統中不同的app擁有不同的進程,每個進程都在各自的記憶體區域。相互不同通信,這是linux底層決定的。不同的進程之間想要通信,就需要通過Binder。
Binder驅動位於系統的底層,有一塊共用記憶體區域,不同的進程想要相互通信,就需要通過Binder驅動,被訪問的進程也就是服務端會在Binder驅動這塊共用記憶體中產生一個引用。
客戶端進程會持有同樣的引用到這塊共用記憶體中找到這個引用。所有的通信都是在這塊共用記憶體中完成的。
進程A想訪問進程B,進程A中aidl文件中的proxy會將數據寫到底層Binder驅動裡面,然後讓Binder驅動裡面的c、c++去訪問進程B中aidl文件的Stub裡面的函數。
執行mRemote.transact(Stub.TRANSACTION_connect, _data, _reply, 0);之後,binder驅動通過IBinder引用找到服務端進程aidl引用,調用服務端aidl對象中的方法,
通過onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)回調給客戶端。
什麼時候把AIDL引用寫入到Binder驅動的,在構造函數初始化的時候,也會執行父類Binder的構造函數,在父類的構造函數中執行寫入。
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public Binder(){
//native方法
init();
}
private native final void init();