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

提示:源码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入门------点击打开链接





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值