Binder學習總結_native(1)

yangxi_001發表於2016-12-27

這幾天一直在看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)

Unknown macro: {                                                  intr = new BpXXXService(obj); //如果queryLocalInterface返回NULL,就構造一個BpXXXService返回,Client得到的正是這個BpXXXService        }

                                                           
    }                                                               
    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學習後會繼續分析總結。


轉自:http://blog.csdn.net/ljsbuct/article/details/7991838

相關文章