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

關聯繫列
Android AOSP基礎系列
Android系統啓動系列
應用進程啓動系列
Android深刻四大組件系列
Android深刻理解Context系列
Android深刻理解JNI系列
Android解析WindowManager
Android解析WMS系列
Android解析AMS系列
Android包管理機制系列
Android輸入系統系列前端

本文首發於微信公衆號「後廠村碼農」android

前言

在上一篇文章中,咱們瞭解了學習Binder前必需要了解的知識點,其中有一點就是Binder機制的三個部分:Java Binder、Native Binder、Kernel Binder,其中Java Binder和Native Binder都是應用開發須要掌握的。Java Binder是須要藉助Native Binder來工做的,所以須要先了解Native Binder,Native Binder架構的原型就是基於Binder通訊的C/S架構,所以咱們先從它開始入手。源碼是基於Android 9.0。程序員

1.基於Binder通訊的C/S架構

在Android系統中,Binder進程間的通訊的使用是很廣泛的,在Android進階三部曲第一部的最後一章,我講解了MediaPlayer框架,這個框架基於C/S架構,並採用Binder來進行進程間通訊,以下圖所示。 微信

uZgTgJ.png

從圖中能夠看出,除了常規C/S架構的Client端和Server端,還包括了ServiceManager,它用於管理系統中的服務。 首先Server進程會註冊一些Service到ServiceManager中,Client要使用某個Service,則須要先到ServiceManager查詢Service的相關信息,而後根據Service的相關信息與Service所在的Server進程創建通訊通路,這樣Client就可使用Service了。架構

2.MediaServer的main函數

Client、Server、ServiceManager三者的交互都是基於Binder通訊的,那麼任意二者的交互均可以說明Binder的通訊的原理,能夠說Native Binder的原理的核心就是ServiceManager的原理,爲了更好的瞭解ServiceManager,這裏拿MediaPlayer框架來舉例,它也是學習多媒體時必需要掌握的知識點。框架

MediaPlayer框架的簡單框架圖以下所示。 函數

uMegMj.png
能夠看到,MediaPlayer和MediaPlayerService是經過Binder來進行通訊的,MediaPlayer是Client端,MediaPlayerService是Server端,MediaPlayerService是系統多媒體服務的一種,系統多媒體服務是由一個叫作MediaServer的服務進程提供的,它是一個可執行程序,在Android系統啓動時,MediaServer也被啓動,它的入口函數以下所示。 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();
    //當前線程加入到線程池
    IPCThreadState::self()->joinThreadPool();
}
複製代碼

註釋1處用於獲取ProcessState實例,在這一過程當中會打開/dev/binder設備,並使用mmap爲Binder驅動分配一個虛擬地址空間用來接收數據。 註釋2處用來獲得一個IServiceManager,經過這個IServiceManager,其餘進程就能夠和當前的ServiceManager進行交互,這裏就用到了Binder通訊。 註釋3處用來註冊MediaPlayerService。 除了註釋3處的知識點在下一篇文章進行介紹,註釋1和註釋2處的內容,本篇文章會分別來進行介紹,先看ProcessState實例。學習

3.每一個進程惟一的ProcessState

ProcessState從名稱就能夠看出來,用於表明進程的狀態,先來查看上一小節的ProcessState的self函數。 frameworks/native/libs/binder/ProcessState.cppthis

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

這裏採用了單例模式,確保每一個進程只有一個ProcessState實例。註釋1處用於建立一個ProcessState實例,參數爲/dev/binder。接着來查看ProcessState的構造函數,代碼以下所示。 frameworks/native/libs/binder/ProcessState.cppspa

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的構造函數中調用了不少函數,須要注意的是註釋1處,它用來打開/dev/binder設備。 註釋2處的mmap函數,它會在內核虛擬地址空間中申請一塊與用戶虛擬內存相同大小的內存,而後再申請物理內存,將同一塊物理內存分別映射到內核虛擬地址空間和用戶虛擬內存空間,實現了內核虛擬地址空間和用戶虛擬內存空間的數據同步操做,也就是內存映射。 mmap函數用於對Binder設備進行內存映射,除了它還有open、ioctl函數,來看看它們作了什麼。 註釋1處的open_driver函數的代碼以下所示。 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設備並返回文件操做符fd,這樣就能夠操做內核的Binder驅動了。註釋2處的ioctl函數的做用就是和Binder設備進行參數的傳遞,這裏的ioctl函數用於設定binder支持的最大線程數爲15(maxThreads的值爲15)。最終open_driver函數返回文件操做符fd。

ProcessState就分析倒這裏,總的來講它作了如下幾個重要的事: 1.打開/dev/binder設備並設定Binder最大的支持線程數。 2.經過mmap爲binder分配一塊虛擬地址空間,達到內存映射的目的。

4.ServiceManager中的Binder機制

回到第一小節的MediaServer的入口函數,在註釋2處調用了defaultServiceManager函數。 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函數生成了gDefaultServiceManager,其內部調用了ProcessState的getContextObject函數,代碼以下所示。 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函數中直接調用了getStrongProxyForHandle函數,注意它的參數的值爲0,那麼handle的值就爲0,handle是一個資源標識。註釋1處查詢這個資源標識對應的資源(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是一一對應的,BpBinder會經過handle來找到對應的BBinder。 咱們知道在ServiceManager中建立了BpBinder,經過handle(值爲0)能夠找到對應的BBinder。

usIeXQ.png

分析完了ProcessState的getContextObject函數,回到interface_cast函數:

gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
複製代碼

interface_cast具體實現以下所示。 frameworks/native/libs/binder/include/binder/IInterface.h

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

當前的場景中,INTERFACE的值爲IServiceManager,那麼替換後代碼以下所示。

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

咱們接着來分析IServiceManager。

4.2 解密IServiceManager

BpBinder和BBinder負責Binder的通訊,而IServiceManager用於處理ServiceManager的業務,IServiceManager是C++代碼,所以它的定義在IServiceManager.h中。 frameworks/native/libs/binder/include/binder/IServiceManager.h

class IServiceManager : public IInterface
{
public:
    DECLARE_META_INTERFACE(ServiceManager)//1
    ...
    //一些操做Service的函數
    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,其內部定義了一些常量和一些操做Service的函數,在註釋1處調用了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,那麼通過替換後的代碼以下所示。

static const ::android::String16 descriptor;       
    //定義asInterface函數
    static ::android::sp<IServiceManager> asInterface(                    
            const ::android::sp<::android::IBinder>& obj);            
    virtual const ::android::String16& getInterfaceDescriptor() const;  
    //定義IServiceManager構造函數
    IServiceManager();          
    //定義IServiceManager析構函數
    virtual ~IServiceManager();     
複製代碼

從DECLARE_META_INTERFACE宏的名稱和上面的代碼中,能夠發現它主要聲明瞭一些函數和一個變量。那麼這些函數和變量的實如今哪呢?答案仍是在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宏是配合使用的,不少系統服務都使用了它們,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",進行替換後的代碼以下所示。

const ::android::String16 IServiceManager::descriptor("android.os.IServiceManager");          
    const ::android::String16&                                          
            IServiceManager::getInterfaceDescriptor() const {              
        return IServiceManager::descriptor;                                
    } 
     //實現了asInterface函數
    ::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() { }                                   
複製代碼

關鍵的點就在於註釋1處,新建了一個BpServiceManager,傳入的參數obj的值爲BpBinder。看到這裏,咱們也就明白了,asInterface函數就是用BpBinder爲參數建立了BpServiceManager,從而推斷出interface_cast函數建立了BpServiceManager,再往上推斷,IServiceManager的defaultServiceManager函數返回的就是BpServiceManager。 BpServiceManager有什麼做用呢,先從BpServiceManager的構造函數看起。 frameworks/native/libs/binder/IServiceManager.cpp

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

impl的值其實就是BpBinder,BpServiceManager的構造函數調用了基類BpInterface的構造函數。 frameworks/native/libs/binder/include/binder/IInterface.h

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
...
};
複製代碼

BpInterface繼承了BpRefBase,BpRefBase的實現以下所示。 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的做用也就知道了,就是它實現了IServiceManager,而且經過BpBinder來實現通訊。

4.3 IServiceManager家族

可能上面講的會讓你有些頭暈,這是由於對各個類的關係不大明確,經過下圖也許你就會豁然開朗。

ufWhRI.png

1.BpBinder和BBinder都和通訊有關,它們都繼承自IBinder。 2.BpServiceManager派生自IServiceManager,它們都和業務有關。 3.BpRefBase包含了mRemote,經過不斷的派生,BpServiceManager也一樣包含mRemote,它指向了BpBinder,經過BpBinder來實現通訊。

5.小節

本篇文章咱們學到了Binder通訊的C/S架構,也知道了Native Binder的原理的核心其實就是ServiceManager的原理,爲了講解ServiceManager的原理,咱們須要一個框架來舉例,那就是MediaPlayer框架。在講解MediaServer的入口函數時,咱們遇到了三個問題,其中前兩個問題相關的知識點ProcessState和IServiceManager都講解到了,下一篇文章會講解第三個問題,MediaPlayerService是如何註冊的。


這裏不只分享大前端、Android、Java等技術,還有程序員成長類文章。

相關文章
相關標籤/搜索