Android Binder原理(二)ServiceManager中的Binder機(jī)制

本文首發(fā)于微信公眾號「后廠技術(shù)官」

前言

在上一篇文章中,我們了解了學(xué)習(xí)Binder前必須要了解的知識點,其中有一點就是Binder機(jī)制的三個部分:Java Binder、Native Binder、Kernel Binder,其中Java Binder和Native Binder都是應(yīng)用開發(fā)需要掌握的。Java Binder是需要借助Native Binder來工作的,因此需要先了解Native Binder,Native Binder架構(gòu)的原型就是基于Binder通信的C/S架構(gòu),因此我們先從它開始入手。源碼是基于Android 9.0。

1.基于Binder通信的C/S架構(gòu)

在Android系統(tǒng)中,Binder進(jìn)程間的通信的使用是很普遍的,在Android進(jìn)階三部曲第一部的最后一章,我講解了MediaPlayer框架,這個框架基于C/S架構(gòu),并采用Binder來進(jìn)行進(jìn)程間通信,如下圖所示。


uZgTgJ.png

從圖中可以看出,除了常規(guī)C/S架構(gòu)的Client端和Server端,還包括了ServiceManager,它用于管理系統(tǒng)中的服務(wù)。
首先Server進(jìn)程會注冊一些Service到ServiceManager中,Client要使用某個Service,則需要先到ServiceManager查詢Service的相關(guān)信息,然后根據(jù)Service的相關(guān)信息與Service所在的Server進(jìn)程建立通信通路,這樣Client就可以使用Service了。

2.MediaServer的main函數(shù)

Client、Server、ServiceManager三者的交互都是基于Binder通信的,那么任意兩者的交互都可以說明Binder的通信的原理,可以說Native Binder的原理的核心就是ServiceManager的原理,為了更好的了解ServiceManager,這里拿MediaPlayer框架來舉例,它也是學(xué)習(xí)多媒體時必須要掌握的知識點。

MediaPlayer框架的簡單框架圖如下所示。

uMegMj.png

可以看到,MediaPlayer和MediaPlayerService是通過Binder來進(jìn)行通信的,MediaPlayer是Client端,MediaPlayerService是Server端,MediaPlayerService是系統(tǒng)多媒體服務(wù)的一種,系統(tǒng)多媒體服務(wù)是由一個叫做MediaServer的服務(wù)進(jìn)程提供的,它是一個可執(zhí)行程序,在Android系統(tǒng)啟動時,MediaServer也被啟動,它的入口函數(shù)如下所示。
frameworks/av/media/mediaserver/main_mediaserver.cpp

int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);
    //獲取ProcessState實例
    sp<ProcessState> proc(ProcessState::self());//1
    sp<IServiceManager> sm(defaultServiceManager());//2
    ALOGI("ServiceManager: %p", sm.get());
    InitializeIcuOrDie();
    //注冊MediaPlayerService
    MediaPlayerService::instantiate();//3
    ResourceManagerService::instantiate();
    registerExtensions();
    //啟動Binder線程池
    ProcessState::self()->startThreadPool();
    //當(dāng)前線程加入到線程池
    IPCThreadState::self()->joinThreadPool();
}

注釋1處用于獲取ProcessState實例,在這一過程中會打開/dev/binder設(shè)備,并使用mmap為Binder驅(qū)動分配一個虛擬地址空間用來接收數(shù)據(jù)。
注釋2處用來得到一個IServiceManager,通過這個IServiceManager,其他進(jìn)程就可以和當(dāng)前的ServiceManager進(jìn)行交互,這里就用到了Binder通信。
注釋3處用來注冊MediaPlayerService。
除了注釋3處的知識點在下一篇文章進(jìn)行介紹,注釋1和注釋2處的內(nèi)容,本篇文章會分別來進(jìn)行介紹,先看ProcessState實例。

3.每個進(jìn)程唯一的ProcessState

ProcessState從名稱就可以看出來,用于代表進(jìn)程的狀態(tài),先來查看上一小節(jié)的ProcessState的self函數(shù)。
frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    gProcess = new ProcessState("/dev/binder");//1
    return gProcess;
}

這里采用了單例模式,確保每個進(jìn)程只有一個ProcessState實例。注釋1處用于創(chuàng)建一個ProcessState實例,參數(shù)為/dev/binder。接著來查看ProcessState的構(gòu)造函數(shù),代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))//1
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);//2
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}

ProcessState的構(gòu)造函數(shù)中調(diào)用了很多函數(shù),需要注意的是注釋1處,它用來打開/dev/binder設(shè)備。
注釋2處的mmap函數(shù),它會在內(nèi)核虛擬地址空間中申請一塊與用戶虛擬內(nèi)存相同大小的內(nèi)存,然后再申請物理內(nèi)存,將同一塊物理內(nèi)存分別映射到內(nèi)核虛擬地址空間和用戶虛擬內(nèi)存空間,實現(xiàn)了內(nèi)核虛擬地址空間和用戶虛擬內(nèi)存空間的數(shù)據(jù)同步操作,也就是內(nèi)存映射。
mmap函數(shù)用于對Binder設(shè)備進(jìn)行內(nèi)存映射,除了它還有open、ioctl函數(shù),來看看它們做了什么。
注釋1處的open_driver函數(shù)的代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp

static int open_driver(const char *driver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);//1
    if (fd >= 0) {
        ...
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//2
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
    }
    return fd;
}

注釋1處用于打開/dev/binder設(shè)備并返回文件操作符fd,這樣就可以操作內(nèi)核的Binder驅(qū)動了。注釋2處的ioctl函數(shù)的作用就是和Binder設(shè)備進(jìn)行參數(shù)的傳遞,這里的ioctl函數(shù)用于設(shè)定binder支持的最大線程數(shù)為15(maxThreads的值為15)。最終open_driver函數(shù)返回文件操作符fd。

ProcessState就分析倒這里,總的來說它做了以下幾個重要的事:
1.打開/dev/binder設(shè)備并設(shè)定Binder最大的支持線程數(shù)。
2.通過mmap為binder分配一塊虛擬地址空間,達(dá)到內(nèi)存映射的目的。

4.ServiceManager中的Binder機(jī)制

回到第一小節(jié)的MediaServer的入口函數(shù),在注釋2處調(diào)用了defaultServiceManager函數(shù)。
frameworks/native/libs/binder/IServiceManager.cpp

sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

    {
        AutoMutex _l(gDefaultServiceManagerLock);
        while (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));//1
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }

    return gDefaultServiceManager;
}

從IServiceManager所在的文件路徑就可以知道,ServiceManager中不僅僅使用了Binder通信,它自身也是屬于Binder體系的。defaultServiceManager中同樣使用了單例,注釋1處的interface_cast函數(shù)生成了gDefaultServiceManager,其內(nèi)部調(diào)用了ProcessState的getContextObject函數(shù),代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);//1
    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            b = BpBinder::create(handle);//2
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

getContextObject函數(shù)中直接調(diào)用了getStrongProxyForHandle函數(shù),注意它的參數(shù)的值為0,那么handle的值就為0,handle是一個資源標(biāo)識。注釋1處查詢這個資源標(biāo)識對應(yīng)的資源(handle_entry)是否存在,如果不存在就會在注釋2處新建BpBinder,并在注釋3處賦值給 handle_entry的binder。最終返回的result的值為BpBinder。

4.1 BpBinder和BBinder

說到BpBinder,不得不提到BBinder,它們是Binder通信的“雙子星”,都繼承了IBinder。BpBinder是Client端與Server交互的代理類,而BBinder則代表了Server端。BpBinder和BBinder是一一對應(yīng)的,BpBinder會通過handle來找到對應(yīng)的BBinder。
我們知道在ServiceManager中創(chuàng)建了BpBinder,通過handle(值為0)可以找到對應(yīng)的BBinder。


usIeXQ.png

分析完了ProcessState的getContextObject函數(shù),回到interface_cast函數(shù):

 gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));

interface_cast具體實現(xiàn)如下所示。
frameworks/native/libs/binder/include/binder/IInterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

當(dāng)前的場景中,INTERFACE的值為IServiceManager,那么替換后代碼如下所示。

inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);
}

我們接著來分析IServiceManager。

4.2 解密IServiceManager

BpBinder和BBinder負(fù)責(zé)Binder的通信,而IServiceManager用于處理ServiceManager的業(yè)務(wù),IServiceManager是C++代碼,因此它的定義在IServiceManager.h中。
frameworks/native/libs/binder/include/binder/IServiceManager.h

class IServiceManager : public IInterface
{
public:
    DECLARE_META_INTERFACE(ServiceManager)//1
    ...
    //一些操作Service的函數(shù)
    virtual sp<IBinder>         getService( const String16& name) const = 0;
    virtual sp<IBinder>         checkService( const String16& name) const = 0;
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated = false,
                                int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
    virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
    enum {
        GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
        CHECK_SERVICE_TRANSACTION,
        ADD_SERVICE_TRANSACTION,
        LIST_SERVICES_TRANSACTION,
    };
};

可以看到IServiceManager繼承了IInterface,其內(nèi)部定義了一些常量和一些操作Service的函數(shù),在注釋1處調(diào)用了DECLARE_META_INTERFACE宏,它的定義在IInterface.h中。
frameworks/native/libs/binder/include/binder/IInterface.h

#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const ::android::String16 descriptor;                        \
    static ::android::sp<I##INTERFACE> asInterface(                     \
            const ::android::sp<::android::IBinder>& obj);              \
    virtual const ::android::String16& getInterfaceDescriptor() const;  \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();     

其中INTERFACE的值為ServiceManager,那么經(jīng)過替換后的代碼如下所示。

    static const ::android::String16 descriptor;       
    //定義asInterface函數(shù)
    static ::android::sp<IServiceManager> asInterface(                    
            const ::android::sp<::android::IBinder>& obj);            
    virtual const ::android::String16& getInterfaceDescriptor() const;  
    //定義IServiceManager構(gòu)造函數(shù)
    IServiceManager();          
    //定義IServiceManager析構(gòu)函數(shù)
    virtual ~IServiceManager();     

從DECLARE_META_INTERFACE宏的名稱和上面的代碼中,可以發(fā)現(xiàn)它主要聲明了一些函數(shù)和一個變量。那么這些函數(shù)和變量的實現(xiàn)在哪呢?答案還是在IInterface.h中,叫做IMPLEMENT_META_INTERFACE宏,代碼如下所示/
frameworks/native/libs/binder/include/binder/IInterface.h

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
    const ::android::String16&                                          \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
            const ::android::sp<::android::IBinder>& obj)               \
    {                                                                   \
        ::android::sp<I##INTERFACE> intr;                               \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

DECLARE_META_INTERFACE宏和IMPLEMENT_META_INTERFACE宏是配合使用的,很多系統(tǒng)服務(wù)都使用了它們,IServiceManager使用IMPLEMENT_META_INTERFACE宏只有一行代碼,如下所示。
frameworks/native/libs/binder/IServiceManager.cpp

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

IMPLEMENT_META_INTERFACE宏的INTERFACE值為ServiceManager,NAME值為"android.os.IServiceManager",進(jìn)行替換后的代碼如下所示。

    const ::android::String16 IServiceManager::descriptor("android.os.IServiceManager");          
    const ::android::String16&                                          
            IServiceManager::getInterfaceDescriptor() const {              
        return IServiceManager::descriptor;                                
    } 
     //實現(xiàn)了asInterface函數(shù)
    ::android::sp<IServiceManager> IServiceManager::asInterface(              
            const ::android::sp<::android::IBinder>& obj)               
    {                                                                   
        ::android::sp<IServiceManager> intr;                               
        if (obj != NULL) {                                              
            intr = static_cast<IServiceManager>(                          
                obj->queryLocalInterface(                               
                        IServiceManager::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new BpServiceManager(obj);//1                        
            }                                                           
        }                                                               
        return intr;                                                    
    }                                                                   
    IServiceManager::IServiceManager() { }                                    
    IServiceManager::~IServiceManager() { }                                   

關(guān)鍵的點就在于注釋1處,新建了一個BpServiceManager,傳入的參數(shù)obj的值為BpBinder。看到這里,我們也就明白了,asInterface函數(shù)就是用BpBinder為參數(shù)創(chuàng)建了BpServiceManager,從而推斷出interface_cast函數(shù)創(chuàng)建了BpServiceManager,再往上推斷,IServiceManager的defaultServiceManager函數(shù)返回的就是BpServiceManager。
BpServiceManager有什么作用呢,先從BpServiceManager的構(gòu)造函數(shù)看起。
frameworks/native/libs/binder/IServiceManager.cpp

class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    explicit BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }
...
}

impl的值其實就是BpBinder,BpServiceManager的構(gòu)造函數(shù)調(diào)用了基類BpInterface的構(gòu)造函數(shù)。
frameworks/native/libs/binder/include/binder/IInterface.h

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
...
};

BpInterface繼承了BpRefBase,BpRefBase的實現(xiàn)如下所示。
frameworks/native/libs/binder/Binder.cpp

BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);

    if (mRemote) {
        mRemote->incStrong(this);           
        mRefs = mRemote->createWeak(this);  
    }
}

mRemote是一個IBinder* 指針,它最終的指向為BpBinder,也就是說BpServiceManager的mRemote指向了BpBinder。那么BpServiceManager的作用也就知道了,就是它實現(xiàn)了IServiceManager,并且通過BpBinder來實現(xiàn)通信。

4.3 IServiceManager家族

可能上面講的會讓你有些頭暈,這是因為對各個類的關(guān)系不大明確,通過下圖也許你就會豁然開朗。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4HtEwN0A-1578825026363)(https://s2.ax1x.com/2019/10/08/ufWhRI.png)]

1.BpBinder和BBinder都和通信有關(guān),它們都繼承自IBinder。
2.BpServiceManager派生自IServiceManager,它們都和業(yè)務(wù)有關(guān)。
3.BpRefBase包含了mRemote,通過不斷的派生,BpServiceManager也同樣包含mRemote,它指向了BpBinder,通過BpBinder來實現(xiàn)通信。

5.小節(jié)

本篇文章我們學(xué)到了Binder通信的C/S架構(gòu),也知道了Native Binder的原理的核心其實就是ServiceManager的原理,為了講解ServiceManager的原理,我們需要一個框架來舉例,那就是MediaPlayer框架。在講解MediaServer的入口函數(shù)時,我們遇到了三個問題,其中前兩個問題相關(guān)的知識點ProcessState和IServiceManager都講解到了,下一篇文章會講解第三個問題,MediaPlayerService是如何注冊的。

更多的見我的原創(chuàng)知識體系:
https://github.com/henrymorgen/android-knowledge-system

這里不僅分享大前端、Android、Java等技術(shù),還有程序員成長類文章。


qrcode_for_gh_28bf22ba9ab4_258.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容