Android------Binder natvite层架构浅析

来源:互联网 发布:剑灵帅气灵男捏脸数据 编辑:程序博客网 时间:2024/06/06 20:41

提示:源码android7.1

这篇文章我会讲解一下c++层的binder架构,我会把我知道的重要知识点都讲出来,希望对binder不太熟悉的朋友有些许帮助。

先列举一下我会说到的文件,讲到该文件时我就不再列举路径了:

framework/native/include/binder/IBinder.h

framework/native/include/binder/Binder.h

framework/native/include/binder/IInterface.h

framework/native/include/binder/BpBinder.h

framework/native/include/binder/IPCThreadState.h

framework/native/include/binder/IServiceManager.h

framework/native/include/binder/ProcessState.h

framework/native/libs/binder/Binder.cpp

framework/native/libs/binder/BpBinder.cpp

framework/native/libs/binder/IInterface.cpp

framework/native/libs/binder/IPCThreadState.cpp

framework/native/libs/binder/ProcessState.cpp

framework/native/libs/binder/IServiceManager.cpp


下面我先给出一张图:



RefBase从字面上是“引用基类”的意思,为什么它在金字塔的顶层了。

这里我要科普一下,看过Android源码中的c++代码,一定不会对sp/wp感到陌生,系统中有大量的sp/wp,在android系统中,通过RefBase,sp(strong pointer)/wp(weak pointer)这一系列强弱引用计数(也可以叫智能指针),可以实现对对象生命周期的管理。

它们所在的文件如下:

system/core/libutils/RefBase.cpp

system/core/include/utils/RefBase.h

system/core/include/utils/StrongPointer.h

使用引用计数的原因有2个:1是为了防止内存泄露,2是为了避免野指针。

如何使用引用计数,假设现在有一个类,如果要用智能指针来引用这个类的对象,必须满足一下2点:

(1)这个类必须是基类RefBase的子类或者间接子类。

(2)这个类必须定义虚析构函数,比如:virtual ~myClass();

RefBase就讲这么多了,毕竟它不是我们关注的重点,回到binder的分析,这张图里的类都很重要,里面有的类里含有xxx,这是要我们自己去定义的,比如xxx=myService,替代进去就可以了。

我这里要借鉴刘超大神的书中所说把binder涉及到的对象进行一下分类,便于下面的讲解:

(1)Binder实体对象:Binder实体对象就是Binder服务的提供者,”Binder实体对象“对应的是“BBinder 对象"

(2)Binder引用对象:Binder引用对象是Binder实体对象在客户端进程的代表,每个引用对象的类型都是BpBinder类,以名称”BpBinder 对象“来代替”Binder引用对象“

(3)Binder代理对象:也可以叫做Binder接口对象,它主要是为客户端的上层应用提供接口服务,从IInterface派生,它实现Binder服务的函数接口,当然只是一个转掉的空壳,通过代理对象,应用能像使用本地对象一样使用远端的实体对象提供的服务。

(4)IBinder对象,BBinder和BpBinder都是从IBinder类派生,其实不用刻意的去区分引用对象和实体对象,可以用”IBinder“来统一称呼。



这里我把我文章的讲解的内容这里梳理一下:

1.讲解一下binder的大致框架

2.讲解一下server和client获得servicemanager接口的过程

3.提一下java层的BinderService


1》讲一下binder的大体框架

1,IBinder,BBinder,BpBinder

在c++层次我们就能看到binder的主要一些核心类了,BBinder和BpBinder都由IBinder派生,下面我把IBinder.h的部分内容贴出来:

class IBinder : public virtual RefBase{public:    enum {        FIRST_CALL_TRANSACTION  = 0x00000001,        LAST_CALL_TRANSACTION   = 0x00ffffff,        PING_TRANSACTION        = B_PACK_CHARS('_','P','N','G'),        DUMP_TRANSACTION        = B_PACK_CHARS('_','D','M','P'),        SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),        INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),        SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),        // Corresponds to TF_ONE_WAY -- an asynchronous call.        FLAG_ONEWAY             = 0x00000001    };                          IBinder();    /**     * Check if this IBinder implements the interface named by     * @a descriptor.  If it does, the base pointer to it is returned,     * which you can safely static_cast<> to the concrete C++ interface.     */    virtual sp<IInterface>  queryLocalInterface(const String16& descriptor);    /**     * Return the canonical name of the interface provided by this IBinder     * object.     */    virtual const String16& getInterfaceDescriptor() const = 0;    virtual bool            isBinderAlive() const = 0;    virtual status_t        pingBinder() = 0;    virtual status_t        dump(int fd, const Vector<String16>& args) = 0;    static  status_t        shellCommand(const sp<IBinder>& target, int in, int out, int err,                                         Vector<String16>& args,                                         const sp<IResultReceiver>& resultReceiver);    virtual status_t        transact(   uint32_t code,                                        const Parcel& data,                                        Parcel* reply,                                        uint32_t flags = 0) = 0;    class DeathRecipient : public virtual RefBase    {    public:        virtual void binderDied(const wp<IBinder>& who) = 0;    };    /**     * Register the @a recipient for a notification if this binder     * goes away.  If this binder object unexpectedly goes away     * (typically because its hosting process has been killed),     * then DeathRecipient::binderDied() will be called with a reference     * to this.     *     * The @a cookie is optional -- if non-NULL, it should be a     * memory address that you own (that is, you know it is unique).     *     * @note You will only receive death notifications for remote binders,     * as local binders by definition can't die without you dying as well.     * Trying to use this function on a local binder will result in an     * INVALID_OPERATION code being returned and nothing happening.     *     * @note This link always holds a weak reference to its recipient.     *     * @note You will only receive a weak reference to the dead     * binder.  You should not try to promote this to a strong reference.     * (Nor should you need to, as there is nothing useful you can     * directly do with it now that it has passed on.)     */    virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,                                        void* cookie = NULL,                                        uint32_t flags = 0) = 0;    /**     * Remove a previously registered death notification.     * The @a recipient will no longer be called if this object     * dies.  The @a cookie is optional.  If non-NULL, you can     * supply a NULL @a recipient, and the recipient previously     * added with that cookie will be unlinked.     */    virtual status_t        unlinkToDeath(  const wp<DeathRecipient>& recipient,                                            void* cookie = NULL,                                            uint32_t flags = 0,                                            wp<DeathRecipient>* outRecipient = NULL) = 0;    virtual bool            checkSubclass(const void* subclassID) const;    typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);    virtual void            attachObject(   const void* objectID,                                            void* object,                                            void* cleanupCookie,                                            object_cleanup_func func) = 0;    virtual void*           findObject(const void* objectID) const = 0;    virtual void            detachObject(const void* objectID) = 0;    virtual BBinder*        localBinder();    virtual BpBinder*       remoteBinder();protected:    virtual          ~IBinder();private:};
我们看到在IBinder中有很多纯虚函数,也就是说IBinder是一个抽象类,是不能实例化的,所以必须要有派生类,而BBinder和BpBinder就出现了,它两都继承了IBInder,并且把这些纯虚函数都重写了,所以BBinder和BpBinder是可以实例化的,这里还要注意IBinder是可以使用应用计数的,也就是用智能指针来管理它的对象,也就是BpBinder和BBinder的对象。这里有两个函数,localBinder和remoteBinder,用它们可以得到BBinder和BpBinder,看函数意思也知道,一个得到本地实体对象,一个是得到引用对象。


2.IInterface,BnInterface,BpInterface

下面介绍一下IInterface以及他的两个派生类:BnInterface和BpInterface

首先看一下Interface.h,节选一些代码贴出来:

class IInterface : public virtual RefBase{public:            IInterface();            static sp<IBinder>  asBinder(const IInterface*);            static sp<IBinder>  asBinder(const sp<IInterface>&);protected:    virtual                     ~IInterface();    virtual IBinder*            onAsBinder() = 0;};// ----------------------------------------------------------------------template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){    return INTERFACE::asInterface(obj);}template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder{public:    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);    virtual const String16&     getInterfaceDescriptor() const;protected:    virtual IBinder*            onAsBinder();};// ----------------------------------------------------------------------template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public:                                BpInterface(const sp<IBinder>& remote);protected:    virtual IBinder*            onAsBinder();};#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();                                            \#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() { } ......template<typename INTERFACE>inline IBinder* BpInterface<INTERFACE>::onAsBinder(){    return remote();}......

看IInterface的定义知道,它也是可以使用引用计数的,并且他也是一个抽象类,BnInterface和BpInterface都继承了它,并且实现了它的纯虚函数onAsBinder

这里不同的是BnInterface它还继承与BBinder,而BpInterface另一个继承对象为BpRefBase,这里为什么要这样设计了,先看一下BpRefbase

class BpRefBase : public virtual RefBase{protected:                            BpRefBase(const sp<IBinder>& o);    virtual                 ~BpRefBase();    virtual void            onFirstRef();    virtual void            onLastStrongRef(const void* id);    virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);    inline  IBinder*        remote()                { return mRemote; }    inline  IBinder*        remote() const          { return mRemote; }private:                            BpRefBase(const BpRefBase& o);    BpRefBase&              operator=(const BpRefBase& o);    IBinder* const          mRemote;    RefBase::weakref_type*  mRefs;    std::atomic<int32_t>    mState;};
我们看到在BpRefBase内部是有一个mRemote成员的,它是一个指向IBinder的指针。因为BpInterface继承了BpRefBase,所以BpInterface先天就内置了一个mRemote成员,
这个mRemote记录的其实就是BpBinder对象,不让BpInterface直接继承BpBinder是为了让开发更加灵活,同时Binder的内部实现和上层完全隔开了,用户完全不知道BpBinder的存在。

在实际的开发中,我们完全可以创建多个聚合同一BpBinder的代理对象,这个代理对象其实对应着同一个远端binder实体,用户可以创建很多个代理对象(也叫代理接口)也意为着方便了用户的使用。

在编写c++层的binder时,BpInterface和BnInterface都是用户需要去继承的类,它们是代理对象,也是直接交互的对象。


3,DECLARE_META_INTERFACE,IMPLEMENT_META_INTERFACE

下面我要提一下2个重要的宏,android巧妙的通过DECLARE_META_INTERFACE(INTERFACE)和IMPLEMENT_META_INTERFACE(INTERFACE, NAME) 将通信和业务牢牢的栓在了一起。这2个宏我刚才已经贴出来了,也是在IInterface.h中。这里只有告你大家这2个宏很重要,具体的分析在下面我会讲到。


4,ProcessState

每个进程只有一个ProcessState,它是独一无二的,ProcessState的字面意思就是进程状态,来看下ProcessState的定义,在ProcessState.h中

class ProcessState : public virtual RefBase{public:    static  sp<ProcessState>    self();            void                setContextObject(const sp<IBinder>& object);            sp<IBinder>         getContextObject(const sp<IBinder>& caller);                    void                setContextObject(const sp<IBinder>& object,                                                 const String16& name);            sp<IBinder>         getContextObject(const String16& name,                                                 const sp<IBinder>& caller);            void                startThreadPool();                            typedef bool (*context_check_func)(const String16& name,                                       const sp<IBinder>& caller,                                       void* userData);                    bool                isContextManager(void) const;            bool                becomeContextManager(                                    context_check_func checkFunc,                                    void* userData);            sp<IBinder>         getStrongProxyForHandle(int32_t handle);            wp<IBinder>         getWeakProxyForHandle(int32_t handle);            void                expungeHandle(int32_t handle, IBinder* binder);            void                spawnPooledThread(bool isMain);                        status_t            setThreadPoolMaxThreadCount(size_t maxThreads);            void                giveThreadPoolName();private:    friend class IPCThreadState;                                    ProcessState();                                ~ProcessState();                                ProcessState(const ProcessState& o);            ProcessState&       operator=(const ProcessState& o);            String8             makeBinderThreadName();            struct handle_entry {                IBinder* binder;                RefBase::weakref_type* refs;            };            handle_entry*       lookupHandleLocked(int32_t handle);            int                 mDriverFD;            void*               mVMStart;            // Protects thread count variable below.            pthread_mutex_t     mThreadCountLock;            pthread_cond_t      mThreadCountDecrement;            // Number of binder threads current executing a command.            size_t              mExecutingThreadsCount;            // Maximum number for binder threads allowed for this process.            size_t              mMaxThreads;            // Time when thread pool was emptied            int64_t             mStarvationStartTimeMs;    mutable Mutex               mLock;  // protects everything below.            Vector<handle_entry>mHandleToObject;            bool                mManagesContexts;            context_check_func  mBinderContextCheckFunc;            void*               mBinderContextUserData;            KeyedVector<String16, sp<IBinder> >                                mContexts;            String8             mRootDir;            bool                mThreadPoolStarted;    volatile int32_t            mThreadPoolSeq;};
ProcessState中有一个mDriverFD,这个值用来记录binder驱动对应的句柄值,以便随时和binder驱动通信,ProcessState采用了单例模式,来看它的ProcessState.cpp:

sp<ProcessState> ProcessState::self(){    Mutex::Autolock _l(gProcessMutex);    if (gProcess != NULL) {        return gProcess;    }    gProcess = new ProcessState;    return gProcess;}ProcessState::ProcessState()    : mDriverFD(open_driver())    , 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) {        // mmap the binder, providing a chunk of virtual address space to receive transactions.        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);        if (mVMStart == MAP_FAILED) {            // *sigh*            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");            close(mDriverFD);            mDriverFD = -1;        }    }    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");}

ProcessState在构造时会打开binder驱动,而且如果mDriverFD>0(也就是说不是servicemanager)就对打开的驱动文件进行内存映射操作。ProcessState中还有一个mHandleToObject比较有用,它是该进程中记录所有BpBinder的表,


5.IPCThreadState

IPCThreadState和驱动之间耦合的很厉害,BpBinder会和IPCThreadState打交道,然后IPCThreadState就和驱动打交道。我们知道借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员,友元类中的所有成员函数都是另外一个类的友元函数,在上面ProcessState中可以看到,IPCThreadState被声明为了ProcessState的友元类,也就是说IPCThreadState中的所有函数都可以访问ProcessState的private成员。


2》server和client获取servicemanager接口的过程

先看一下servicemanager的关系图,实际上系统中只有Iservicemanager,BpServiceManger,系统中并没有BnServiceManger,那是因为android弄了一个service_manager.c来充当BnServiceManager的角色,在servicemanager篇中我么已经说过这个它的main函数了。



获取servicemanager远程接口的函数是defaultServiceManager,在Iservicemanager..cpp中

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

其中gDefaultServiceManager定义在Static.cpp中sp<IServiceManager> gDefaultServiceManager;

从defaultServiceManager函数看出gDefaultServiceManager是单例模式,该函数中最重要的一句就是

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

我们仔细分析一下,首先通过ProcessState::self()得到一个ProcessState的单例对象gProcess,ProcessState在创建的时候会通过open函数打开驱动文件/dev/binder/,并且将返回的设备描述符保存在mDriverFD中。然后调用得到的gProcess的getContextObject函数

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/){    return getStrongProxyForHandle(0);}
继续跟踪getStrongProxyForHandle(0)
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){sp result;    AutoMutex _l(mLock);    handle_entry* e = lookupHandleLocked(handle);    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 = new BpBinder(handle);             e->binder = b;            if (b) e->refs = b->getWeakRefs();            result = b;        } else {result.force_set(b);            e->refs->decWeak(this);        }    }    return result;} 

这里生成了BpBInder(0),于是上面的代码变成了gDefaultServiceManager = interface_cast<IServiceManager>(BpBInder(0));

接着看interface_cast函数,实际上它是一个很重要的类型转换函数,在IInterface.h中,

template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){    return INTERFACE::asInterface(obj);}
即调用了IServiceManager:asInterface(BpBinder(0));

还记得上面的IMPLEMENT_META_INTERFACE宏吗,该asInterface函数就是在这个宏里面定义的

IServiceManager具体的定义如下

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
 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;                                                    \    } 
这里传进来的obj参数为BpBinder(0),INTERFACE为IServiceManager,
这里BpBinder(0)->queryLocalInterface会调用IBinder的queryLocalInterface

sp<IInterface>  IBinder::queryLocalInterface(const String16& /*descriptor*/){    return NULL;}
那么这里intr==null

intr = new BpServiceManager(BpBinder(0))

这样ServiceManager的远程接口就创建完成了,它其实是一个BpServiceManager,包含了一个句柄值为0的BpBinder引用对象


3》其实Binder服务可以分为2种,一种是实名服务,一种是匿名服务,它们从开发到使用没有任何区别,唯一的区别是实名服务可以用servicemanager查找到,如ActivityManagerService,PowerManagerService,匿名服务不能用servicemanager查找到,比如frameworks层提供的一种启动java匿名binder服务的方法:

首先某个应用通过调用binderService方法发出一个intent,Framework根据intent找到对应的组件service并启动它,包含在service中的binder服务也同时创建出来,随后,framework会把服务的IBinder对象通过ConnectivityManager的回调方法onServiceConnected传回到应用,这样应用客户端就得到匿名BInder服务的引用对象,也就能使用组件Service中的匿名BInder服务了,在这里Frameworks中的Intent代替了Binder服务的名称来查找对应的服务,同时也承担了ServiceManager的工作。



参考文献:《深入解析Android5.0系统》;《Android开发艺术探索》;《深入理解Android卷1》;《深入理解Android卷3》;红茶一杯话binder------点击打开链接;gityuan的binder系列------点击打开链接;罗升阳的binder系列------点击打开链接;Andriod Binder机制------点击打开链接;Android深入浅出之binder机制------点击打开链接;理解Android的binder机制-----点击打开链接;轻松理解Androidbinder------点击打开链接;binder service入门------点击打开链接





原创粉丝点击