Binder學習總結_native(1)
這幾天一直在看binder的結構,感嘆這樣天才的設計。
現在只研究到binder的native框架,在IPCThreadState以下,真正的driver和資料交換還需要進一步研究。在此記錄一些目前的體會。
1.IInterface的作用
個人感覺,這個IInterface嚴格上講,並不是Binder這個框架的一部分。
它的作用是提供了一個common的方式,可以將IBinder與Service進行顯示的轉換。
因為在進行IPC時,實際的service IXXXService要轉換成IBinder,才能傳遞給ServiceManager進行註冊檢索,或者傳遞給Client進行呼叫。
而且Client拿到ServiceManager回傳的IBinder以後,又要轉換回IXXXService進行功能呼叫,所以IInterface產生了,提供了IXXXService與IBinder互相轉換的功能。
(1)IXXXService轉換IBinder實現:
IXXXService繼承自IInterface,所以IInterface中的asBinder()方法,會將自身,也就是IXXXService轉換成一個IBinder物件。
sp<IBinder> IInterface::asBinder()
{
return this ? onAsBinder() : NULL;
}
這個onAsBinder()是一個虛擬方法,實際上是有IInterface的兩個子類BpInterface和BnInterface實現的。
BpInterface的實現:
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
return remote(); //呼叫它的父類BpRefBase的remote()方法,返回IBinder,其實就是一個BpBinder
}
BnInterface的實現:
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this; //就是返回自身,因為BnInterface就是從BBinder繼承的,BBinder又是繼承自IBinder
}
(2)IBinder轉換IXXXService實現:
當一個Client拿到ServiceManager返回的IBinder時,需要轉換為IXXXService介面,才能呼叫它的功能。
這個轉換,是由IInterface中定義的巨集DECLARE_META_INTERFACE來宣告的asInterface完成的,並由巨集IMPLEMENT_META_INTERFACE實現的。
將巨集程式碼IMPLEMENT_META_INTERFACE展開後得到:
Android::sp<IXXXService> I##INTERFACE::asInterface(
const android::sp<android::IBinder>& obj)
{
android::sp<IXXXService> intr;
if (obj != NULL) {
intr = static_cast<IXXXService*>(
obj->queryLocalInterface( //先呼叫queryLocalInterface,這個方法是IBinder定義的,預設實現是返回NULL,而在BBinder的子類BnInterface中,過載了該方法,返回this,而
//BpInterface並沒有過載,使用IBinder的預設實現,返回NULL。
IXXXService::descriptor).get());
if (intr == NULL)
}
return intr;
}
總結一下,如果傳進來的obj引數,是一個BBinder,就返回自身(這種情況應該是service和client在同一程式),如果是一個BpBinder,就new一個代理物件返回(這種情況應該是service和client在不同程式)。
2.IBinder, BBinder和BpBinder
這3個類,是對Android Binder框架的抽象,其實這個BBinder,改成BnBinder可能更形象一些。
但是要注意的是,一個IXXXService的繼承圖中,BpBinder並不在這個繼承關係之中,也就是說BpBinder並沒有子類。但是BBinder是在這個繼承關係當中的,它的子類就是BnInterface。
換句話說,BBinder和BpBinder的功能並不是對稱的,以前就是沒有理解到這一點,才會一直很糊塗。
BpBinder的是存在於BpRefBase中的mRemote的成員變數中。從Client呼叫Service的過程中分析,就更清楚了。
假設有一個IXXXService介面:
class IXXXService : public IInterface {
....
public void helloWorld(const char* str);
....
}
(1)client呼叫service
client得到一個BpXXXService以後
(a)會呼叫BpXXXService實現的helloWorld,它會將str引數打包到Parcel中。然後呼叫remote()->transact(xxx)
(b)remote()是在BpXXXService的父類BpRefBase中實現的,返回的就是一個BpBinder.實際上呼叫的就是BpBinder的transact
(c)BpBinder的transact實現,就是直接呼叫IPCThreadState::self()->transact()傳送資料。
(2)service接收client請求:
(a)通過IPCThreadState接收到client的請求後,首先會呼叫BBinder的transact方法。
(b)BBinder的transact方法又會呼叫子類實現的虛擬方法onTransact。這個虛擬方法是在BnXXXService中實現的。
(c)onTransact方法,會通過傳遞進來的引數來判斷,需要呼叫IXXXService中的那個方法,示例中只有一個helloWorld方法。
(d)直接呼叫helloWorld,就會找到它的真正實現,也就是BnXXXService的子類XXXService中的helloWorld方法。
總結一下,從上面的流程當中就可以看出前文說的,BpBinder並不在繼承關係當中,它只是一個打包資料,並通過IPCThreadState::self()->transact()方法傳送出去。
而BBinder和BnXXXService的作用,就是接收IPCThreadState傳遞過來的資訊,解包資料,並呼叫XXXService真正的實現。
IPC的資料處理,Binder Driver和ServiceManager學習後會繼續分析總結。
相關文章
- Binder總結篇1-Binder原理
- shell學習總結-1
- Redis學習總結1Redis
- 學習心得總結(1)
- bootstrap學習總結1boot
- 由淺入深 學習 Android Binder(三)- java binder深究(從java到native)AndroidJava
- Binder總結篇2-Binder使用
- Tomcat學習總結1Tomcat
- Binder學習(二)Binder機制解析
- Binder機制分析(1)——Binder結構簡介
- MySQL深入研究--學習總結(1)MySql
- IOS學習總結(1)——關於併發iOS
- 學習總結
- h5與native互動總結1H5
- 韓語學習筆記(1-5)溫習總結筆記
- 前端學習輯錄(1):js繼承總結前端JS繼承
- JAVAWEB學習總結,DAY4(JDBC1)JavaWebJDBC
- MongoDB儲存引擎-MMAPv1學習總結MongoDB儲存引擎
- Binder學習(三)通過AIDL分析Binder通訊流程AI
- mysqlimport學習總結MySqlImport
- Maven學習總結Maven
- MyBatis 學習總結MyBatis
- awk 學習總結
- JNI 學習總結
- tkinter學習總結
- SVG學習總結SVG
- vue學習總結Vue
- WorkFlow學習總結
- HTML學習總結HTML
- Mybatis學習總結MyBatis
- Kafka 總結學習Kafka
- Typescript學習總結TypeScript
- 【TS】學習總結
- lua 學習總結
- vue 學習總結Vue
- HSF學習總結
- ElasticSearch 學習總結Elasticsearch
- BOM學習總結