图解Android - Binder 和 Service

Zygote启动过程 一文中咱们说道,Zygote一辈子中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深刻了解这些Service 以前,咱们首先要了解 什么是Service?它的工做原理是什么?html

 

 1. Service是什么?

  简单来讲,Service就是提供服务的代码,这些代码最终体现为一个个的接口函数,因此,Service就是实现一组函数的对象,一般也称为组件。Android 的Service 有如下一些特色:java

  1. 请求Service服务的代码(Client)  和 Service自己(Server) 不在一个线程,不少状况下不在一个进程内。跨进程的服务称为远端(Remote)服务,跨进程的调用称为IPC。一般应用程序经过代理(Proxy)对象来访问远端的Service。
  2. Service 能够运行在native 端(C/C++),也能够运行在Java 端。一样,Proxy 能够从native 端访问Java Service, 也能够从Java端访问native service, 也就是说,service的访问与语言无关。
  3. Android里大部分的跨进程的IPC都是基于Binder实现。
  4. Proxy 经过 Interface 类定义的接口访问Server端代码。
  5. Service能够分为匿名和具名Service. 前者没有注册到ServiceManager, 应用没法经过名字获取到访问该服务的Proxy对象。
  6. Service一般在后台线程执行(相对于前台的Activity), 但Service不等同于Thread,Service能够运行在多个Thread上,通常这些Thread称为 Binder Thread.

 

   要了解Service,咱们得先从 Binder 入手。node

  2.  Binder

   

    先给一张Binder相关的类图一瞰Binder全貌,从上面的类图(点击看大图)跟Binder大体有这么几部分:linux

           Native 实现:  IBinder,  BBinder, BpBinder, IPCThread, ProcessState, IInterface, etcandroid

           Java 实现:  IBinder, Binder, BinderProxy, Stub, Proxy.设计模式

           Binder Driver: binder_proc, binder_thread, binder_node, etc.服务器

    咱们将分别对这三部分进行详细的分析,首先从中间的Native实现开始。cookie

    一般来讲,接口是分析代码的入口,Android中'I' 打头的类通通是接口类(C++里就是抽象类), 天然,分析Binder就得先从IBinder下手。先看看他的定义。网络

          

class IBinder : public virtual RefBase
{
public:
    ...
    virtual sp<IInterface>  queryLocalInterface(const String16& descriptor); //返回一个IInterface对象
    ...
    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;
    virtual status_t        transact(   uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0) = 0;
    virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,
                                        void* cookie = NULL,
                                        uint32_t flags = 0) = 0;
    virtual status_t        unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                            void* cookie = NULL,
                                            uint32_t flags = 0,
                                            wp<DeathRecipient>* outRecipient = NULL) = 0;
    ...
    virtual BBinder*        localBinder();  //返回一个BBinder对象
    virtual BpBinder*       remoteBinder(); //返回一个BpBinder对象
};

    有接口必然有实现,从图中能够看出,BBinder和BpBinder都是IBinder的实现类,它们干啥用的,有啥区别?有兴趣同窗能够去分别去读读他们的代码,分别在数据结构

  •  Bpinder: frameworks/native/lib/binder/BpBinder.cpp
  •  BBinder: frameworks/native/lib/binder/Binder.cpp

    这里咱们简单总结一下他们的区别:

接口 BBinder BpBinder
queryLocalInterface() 没有实现, 默认实现 IBinder 默认{reutrn NULL};   没有实现 IBinder 默认实现 {return NULL}
getInterfaceDescriptor()   {return sEmptyDescriptor;}       (this)->transact(INTERFACE_TRANSACTION, send, &reply);
     ...
    mDescriptorCache = res;  
isBinderAlive()   {return true;} {return mAlive != 0;}
pingBinder() {return NoError;} {transact(PING_TRANSACTION, send, &reply);
linkToDeath() {return INVALID_OPERATION;}   {self->requestDeathNotification(mHandle, this);}
unlinkToDeath()   {return INVALID_OPERATION;} {self->clearDeathNotification(mHandle, this);}
localBinder() {return this;} 没有实现, IBinder默认实现 {return NULL};
remoteBinder() 没有实现,IBinder默认实现 {return NULL;} {return this};
transact() {err = onTransact(code, data, reply, flags);} IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
onTransact()

      switch (code) {
        case INTERFACE_TRANSACTION:
            reply->writeString16(getInterfaceDescriptor());
            return NO_ERROR;        ...

没有实现

 

 

 

   

 

 

 

 

 

 

 

     

 

 

看出来了吧,它们的差别在于它们是通讯两端的不一样实现,BBinder是服务端,而BpBinder是客户端,为何这么说?

  1.  pingBinder, BBinder直接返回OK,而BpBinder须要运行一个transact函数,这个函数具体作什么,咱们后面会介绍。
  2.  linkToDeath()是用来在服务挂的时候通知客户端的,那服务端固然不须要本身监视本身咯,因此BBinder直接返回非法,而Bpbinder须要经过requestDeathNotification()要求某人完成这个事情,到底是谁提供这个服务?答案后面揭晓。
  3.  在Android中,remote通常表明某个远端对象的本地代理,想象一下航空公司和机票代理,BBinder是航空公司,固然没有remote的了,那BpBinder就是机票代理了,因此remote()天然返回本身了。
  4.  Transact的英文意思是交易,就是买卖嘛,那天然transact()就是买的操做,而onTransact()就是卖的操做,BBinder的transact()的实现就是onTransact(), 航空公司的买票固然不用经过机票代理了,直接找本身人就行了。

因此结论是,BBinder表明着服务端,而BpBinder则是它在客户端的代理,客户程序经过BpBinder的transact()发起请求,而服务器端的BBinder在onTranscat()里响应请求,并将结果返回。

但是交易确定有目标的吧,回到航空公司和机票代理的例子,若是要订去某个地方的机票,咱们怎么也得先查询一下都有那些航班,而后才能告诉机票代理订具体的航班号吧。这里的查询和预订能够当作服务的接口函数,而航班号就是咱们传递给机票代理的参数。客户程序经过queryLocalInterface() 能够知道航空公司都提供哪些服务。

但是奇怪的是BBinder和BpBinder都没有实现这个接口啊,那确定另有他人实现这个类了,这我的就是IInterface.h, 看看代码

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return this;
    return NULL;
}

 
BnInterface<INTERFACE> 对象将本身强制转换成 IInterface对象返回,看看BnInterface的定义:

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();
};

 

是一个模板类,继承了BBinder, 还有模板 INTERFACE。咱们刚才已经看过,BBinder没有实现queryLocalInterface(), 而BnInterface 返回本身,能够他并无继承IInterface, 怎么能够强制转换呢,惟一的解释就是 INTERFACE模板必须继承和实现IInterface.

class IInterface : public virtual RefBase
{
public:
            IInterface();
            sp<IBinder> asBinder();
            sp<const IBinder>   asBinder() const;           
protected:
    virtual                     ~IInterface();
    virtual IBinder*            onAsBinder() = 0;
};

 

这也太简单了吧,只是定义了 从Interface 到 IBinder的转换接口 asBinder, 而刚才咱们研究的queryLocalInterface() 正好反过来,说明IBinder 和 IInterface 之间是能够互转的,一我的怎么能够变成另一我的呢?惟一的解释就是这我的有双重性格,要么他同时继承 IInterface 和 IBinder, 要么他体内有这两个对象同时存在,不卖关子了,在服务端,这个双重性格的人就是BnXXX, XXX 表明某个具体的服务,咱们以图中的BnMediaPlayer为例,看看他的定义

class BnMediaPlayer: public BnInterface<IMediaPlayer>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};

class IMediaPlayer: public IInterface
{
public:
    DECLARE_META_INTERFACE(MediaPlayer);
    ...

}

 

这下本性都露出来了,IBinder 和 IInterface 的影子都露出来了,让咱们用图梳理一下 (箭头表明继承关系)

             

概括一下,

  1.  BBinder 实现了大部分的IBinder 接口,除了onTransact() 和 queryLocalInterface(), getInterfaceDescriptor();
  2.  BnInterface 实现了IBinder的queryLocalInterface()和getInterfaceDescriptor(), 可是其必须借助实际的接口类。
  3.  BnMediaPlayer只是定义了onTransact(), 没有实现。
  4.  onTransact()的具体实如今Client类。

为何搞得那么复杂?Google 是但愿经过这些封装尽量减小开发者的工做量,开发一个native的service 开发者只须要作这么几件事(上图中深色部分):

  1. 定义一个接口文件, IXXXService, 继承IInterface
  2. 定义BnXXX(), 继承 BnInterface<IXXXService)
  3. 实现一个XXXService类,继承BnXXX(), 并具体实现onTransact() 函数。

那客户端呢? 咱们的目标是找到一个类,它必须同时拥有IBinder 和 IIterface的特性, 先看看BpBinder 吧

   

class BpBinder : public IBinder

 

跟IInterface 没有关系,那必定是别人,看看BpInterface 吧,

template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
    BpInterface(const sp<IBinder>& remote);
protected:
    virtual IBinder*            onAsBinder();
};

 

咱们刚才已经知道了,INTERFACE 是 IMediaPlayer, 它继承了IInterface, IInterface 的对象找到了, 但跟IBinder 不要紧?只剩下BpRefBase 了,

class BpRefBase : public virtual RefBase
{
protected:
    ...
    inline IBinder*        remote()                { return mRemote; }
    ...
private:
    ...
    IBinder* const          mRemote;
    RefBase::weakref_type*  mRefs;
    volatile int32_t        mState;
};

 

 有了,BpRefBase 里有IBinder 成员变量,看来在客户端,没有一个类同时继承IBinder 和 IInterface, 可是有一个类继承了其一,但包含了另一个,这种在设计模式里成为组合(Composition).

 仍是不太明白?仍是用图解释吧,

 

看明白了?从BpInterface开始,经过BpRefBase 咱们能够找到IBinder, 这个转换就在 asBinder() 的实现里,看看代码

sp<IBinder> IInterface::asBinder(){
    return this ? onAsBinder() : NULL;
}

sp<const IBinder> IInterface::asBinder() const{
    return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
}

template<typename INTERFACE> inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
    return remote();
}

template<typename INTERFACE> IBinder* BnInterface<INTERFACE>::onAsBinder()
{
    return this;
}

这里印证咱们上面两张图的正确性,onAsBinder是转换的发生的地方,服务端(BnInterface)的实现直接返回了本身,由于它继承了二者,而客户端(BpInterface)则须要经过remote()(返回mRemote 成员变量)获取,由于他本身自己不是IBinder,

那个BpRefbase的mRemote是如何被赋值的?看看如下代码

//frameworks/native/libs/binder/binder.cpp
BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)
{
   ...
}

 

//frameworks/native/include/binder/iinterface.h
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
{
}

 

//frameworks/av/media/libmedia/IMediaPlayer.cpp
class
BpMediaPlayer: public BpInterface<IMediaPlayer> { public: BpMediaPlayer(const sp<IBinder>& impl) : BpInterface<IMediaPlayer>(impl) { } ... }

 

原来是从子类一级一级注入的,那惟一的问题就是在哪里完成这个注入操做, 立刻搜索"new BpMediaPlayer", 奇怪,居然没有,试试搜索"IMediaPlayer“,发现了一点线索

   //av/media/libmedia/IMediaPlayerService.cpp

   70:     virtual sp<IMediaPlayer> create(
   71:             const sp<IMediaPlayerClient>& client, int audioSessionId) {
   72          Parcel data, reply;
   73:         ...          
   77          remote()->transact(CREATE, data, &reply); 
   78:         return interface_cast<IMediaPlayer>(reply.readStrongBinder()); //reply里读出IBinder,而后转成IMediaPlayer接口对象
   79      }

 

这里经过interface_cast 直接把IBinder 转换成了 IMediaPlayer, interface_cast 到底有什么魔力?

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

 

继续跟进 asInterface, 结果发现里如下代码

#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;                                                    \
    }                                                                   \

 

恍然大悟,原来在DECLARE_META_INTERFACE 这个宏里定义了asInterface, 在IMPLEMENT_META_INTERFACE 里实现了它,这里果真有一个new BpMediaPlayer! 而后把它转换成父父类 IMediaPlayer。

一切都清楚了,用一张图来表示

客户端从远端获取一个IBinder对象,接着生成BpMediaPlayer, 将其转成 IMediaPlayer 接口对象,这是用户程序看到的对象,并经过其调用接口方法,最终调到BpBinder的transact()。

问题又来了,这个transact() 怎么传递到服务端,并最终调到 onTransact()?

回想一下,onTransact() 是IBinder的接口函数吧,并且Server的IBinder实现是BBinder, 那必定有人经过某种方式获得了BBinder对象。

这我的就是Binder Driver. 为了找到真相,必须用源头开始,那就是transact()

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
     ...
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
    ...
    return DEAD_OBJECT;
}

 

IPCThreadState的transact()函数相比IBinder 多了一个mHandle, 啥来历?

BpBinder::BpBinder(int32_t handle)
    : mHandle(handle)

 

构造带进来的,赶忙找“new BpBinder", 结果在ProcessState.cpp 看到了

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    ...
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); 

 

找谁call了getStrongProxyForHandle?为了快速找到调用栈,咱们在BpBinder的构造函数里加了这么几句话:

#include <utils/CallStack.h>
...
CallStack cs;
cs.update();
cs.dump("BpBinder")

 

而后获得了下面的打印

09-29 07:11:14.363  1624  1700 D BpBinder: #00  pc 0001eb34  /system/lib/libbinder.so (android::BpBinder::BpBinder(int)+260)
09-29 07:11:14.363  1624  1700 D BpBinder: #01  pc 0003b9a2  /system/lib/libbinder.so (android::ProcessState::getStrongProxyForHandle(int)+226)
09-29 07:11:14.363  1624  1700 D BpBinder: #02  pc 00032b8c  /system/lib/libbinder.so (android::Parcel::readStrongBinder() const+316) //frameworks/native/libs/binder/Parcel.cpp:247
09-29 07:11:14.363  1624  1700 D BpBinder: #03  pc 000ad9d2  /system/lib/libandroid_runtime.so //frameworks/base/core/jni/android_os_Parcel.cpp:355
09-29 07:11:14.363  1624  1700 D BpBinder: #04  pc 00029c5b  /system/lib/libdvm.so (dvmPlatformInvoke+79) //dalvik/vm/arch/x86/Call386ABI.S:128

 

#04 dvmPlatformInvork 说明这是一个Jni调用,#03 对应的代码是

return javaObjectForIBinder(env, parcel->readStrongBinder());

 

应该是Java传下来一个Parcel对象,而后由本地代码进行解析,从中读出IBinder对象,并最终返回。也就是说,远端有人将这个IBinder对象封在Parcel里。仍是没有头绪?继续顺着调用栈往前看,

#02  对应于下面的代码

status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    ...case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }        
    }
    return BAD_TYPE;
}

 

#bionic/libc/kernel/common/linux/binder.h
struct
flat_binder_object { unsigned long type; unsigned long flags; union { void *binder; signed long handle; }; void *cookie; };

 

原来mHandle就是flat_binder_object里面的handle, 它只是一个数字!这个数据结构定义在Kernel里,是通过Kernel转手的。愈来愈乱了,赶忙整理一下思路:

1.  Kernel 封装了一个数据结构(flat_binder_object),里面带有一个数字(mHandle)。

2.  客户端获取这个数字后,生成一个BpBinder的对象。

3.  而后当客户端须要访问远端服务的时候,将这个数字附上。

回到现实生活,机票代理须要向航空公司查询或订票的话,必定要知道是哪一个航空公司,莫非这个号就是航空公司的编号?

恭喜你,就是那么简单,这个号就对应了服务器端的提供的某一个服务,Android 中每一个Service都有一个号码(根据建立时间递增,0号Service 是ServiceManager,让我用下面的图来描述整个过程吧,

 

1. 在已知服务名的状况下,App 经过getService() 从ServiceManager 获取该服务的信息,该信息封装在Parcel里。

2. 应用程序收到返回的这个Parcel对象(经过Kernel), 从中读取出flat_binder_object 对象,最终从对象中获得服务对应的服务号,mHandle.

3. 以该号码做为参数输入生成一个IBinder对象(实际是BpBinder)。

4. 应用获取该对象后,经过asInterface(IBinder*) 生成服务对应的Proxy对象(BpXXX),并将其强转为接口对象(IXXX),而后直接调用接口函数。

5. 全部的接口对象调用最终会走到BpBinder->transact()函数,这个函数调用IPCThreadState->transact()并以Service号做为参数之一。

6. 最终经过系统调用ioctrl() 进入内核空间,Binder驱动根据传进来的Service 号寻找该Service正处于等待状态的Binder Thread, 唤醒它并在该线程内执行相应的函数,并返回结果给APP。

强调一下:

1. 从应用程序的角度来看,他只认识IBinder 和 IMediaPlayer 这两个类,但真正的实如今BpBinder 和 BpMediaPlayer, 这正是设计模式所推崇的“ Programs to interface, not implementations", 能够说Android 是一个严格遵循设计模式思想精心设计的系统,咱们未来会就这个话题进行深刻的探讨。

2. 客户端应该层层的封装,最终的目的就是获取和传递这个mHandle 值,从图中,咱们看到,这个mHandle至来自与IServiceManager, 他是一个管理其余服务的服务,经过服务的名字咱们能够拿到这个服务对应的Handle号,相似网络域名服务系统。可是咱们说了,IServiceManager也是服务啊,要访问他咱们也须要一个Handle号啊,对了,就如同你必须为你的机器设置DNS 服务器地址,你才能得到DNS 服务。在Android系统里, 默认的将ServiceManger的Handler号设为0,0就是DNS服务器的地址,这样,咱们经过调用 getStrongProxyForHandle(0) 就能够拿到ServiceManager 的IBinder 对象,固然,系统提供一个 getService(char *)函数来帮助完成这个过程。

3.  Android Binder 的设计目标就是让访问远端服务就像调用本地函数同样简单,可是远端的对象不在本地控制以内,咱们必须保证调用过程当中远端的对象不能被析构,不然本地应用程序将颇有可能崩溃。同时,万一远端服务异常退出,如Crash, 本地对象必须知晓从而避免后续的错误。Android 经过 智能指针 和 DeathNotification 来支持这两个要求,咱们会有专门的章节介绍智能指针,这里咱们会在后面简单介绍 DeathNotifycation的实现原理。

Binder的上层设计逻辑简单介绍完毕。咱们接下来看看Binder的底层设计。

3. Binder Driver

咱们知道,Linux的进程空间相互独立,两个进程只能经过Kernel space 进行互访,全部的IPC 机制,最底层的实现都是在Kernel space.  Binder 也是如此,经过系统调用切入内核态,内核寻找到提供服务的进程,唤醒他并进入用户空间,而后在某个线程里调用onTransact(), 完成特定操做,并将结果返回到应用程序。那Binder Driver是如何搭起链接服务端和客户端的这座桥梁呢?

先看看binder driver 内部的数据结构吧:

 下面一一进行解释:

 1.  Binder node:

      咱们前面说过Service 实际上是一个存在于某个进程里的对象,所以,进程PID 和 对象地址能够惟一的标识一个Service 对象,除此以外,由于这个对象可能被不少应用所使用,必须有引用计数来管理他的生命周期。这些工做都必须在内核里完成,Binder node 就是这样一个结构体来管理每一个Service 对象。

     

struct binder_node {
    int debug_id;              //kernel内部标识node的id
    struct binder_work work;   
    union {
        struct rb_node rb_node;
        struct hlist_node dead_node;
    };
    struct binder_proc *proc;  //Service所在进程的结构体
    struct hlist_head refs;    //双向链表头,链表里存放一系列指针,指向引用该Service的binder_ref对象,
    int internal_strong_refs;  //内部强引用计数
    int local_weak_refs;       //弱引用计数
    int local_strong_refs;     //强引用计数
    binder_ptr __user ptr;     //Service对象地址
    binder_ptr __user cookie;  
    unsigned has_strong_ref:1; 
    unsigned pending_strong_ref:1; 
    unsigned has_weak_ref:1;
    unsigned pending_weak_ref:1;
    unsigned has_async_transaction:1;
    unsigned accept_fds:1;
    unsigned min_priority:8;
    struct list_head async_todo;
};

 

 2. binder_ref

 binder_ref 描述了每一个对服务对象的引用,对应与Client端。如上图所示,每一个Ref经过node指向binder_node. 一个进程全部的binder_ref经过两个红黑树(RbTree)进行管理,经过binder_get_ref() 和 binder_get_ref_for_node快速查找。

struct binder_ref {
    /* Lookups needed: */
    /*   node + proc => ref (transaction) */
    /*   desc + proc => ref (transaction, inc/dec ref) */
    /*   node => refs + procs (proc exit) */
    int debug_id;
    struct rb_node rb_node_desc; 
    struct rb_node rb_node_node;
    struct hlist_node node_entry;   
    struct binder_proc *proc;           //应用进程
    struct binder_node *node;
    uint32_t desc;
    int strong;
    int weak;
    struct binder_ref_death *death;  //若是不为空,则client想获知binder的死亡
};

 

 3. binder_proc

 一个进程既包含的Service对象,也可能包含对其余Service对象的引用. 若是做为Service对象进程,它可能会存在多个Binder_Thread。这些信息都在binder_proc结构体进行管理。

struct binder_proc {
    struct hlist_node proc_node; //全局链表 binder_procs 的node之一
    struct rb_root threads; //binder_thread红黑树,存放指针,指向进程全部的binder_thread, 用于Server端
    struct rb_root nodes;   //binder_node红黑树,存放指针,指向进程全部的binder 对象
    struct rb_root refs_by_desc; //binder_ref 红黑树,根据desc(service No) 查找对应的引用
    struct rb_root refs_by_node; //binder_ref 红黑树,根据binder_node 指针查找对应的引用
    int pid;
    struct vm_area_struct *vma;
    struct mm_struct *vma_vm_mm;
    struct task_struct *tsk;
    struct files_struct *files;
    struct hlist_node deferred_work_node;
    int deferred_work;
    void *buffer;
    ptrdiff_t user_buffer_offset;

    struct list_head buffers;
    struct rb_root free_buffers;
    struct rb_root allocated_buffers;
    size_t free_async_space;

    struct page **pages;
    size_t buffer_size;
    uint32_t buffer_free;
    struct list_head todo; //task_list, binder_work链表,存放指针最终指向某个binder_transaction对象
    wait_queue_head_t wait;
    struct binder_stats stats;
    struct list_head delivered_death;
    int max_threads;
    int requested_threads;
    int requested_threads_started;
    int ready_threads;
    long default_priority;
    struct dentry *debugfs_entry;
};

 

为了实现快速的查找,binder_proc内部维护了若干个数据结构,如图中黄色高亮所示,

4. binder_transaction

每一个transact() 调用在内核里都会生产一个binder_transaction 对象,这个对象会最终送到Service进程或线程的todo队列里,而后唤醒他们来最终完成onTransact()调用。

struct binder_transaction {
    int debug_id;             //一个全局惟一的ID
    struct binder_work work; // 用于存放在todo链表里
    struct binder_thread *from; //transaction 发起的线程。若是BC_TRANSACTION, 则为客户端线程,若是是BC_REPLY, 则为服务端线程。
    struct binder_transaction *from_parent; //上一个binder_transaction. 用于client端
    struct binder_proc *to_proc; //目标进程
    struct binder_thread *to_thread; //目标线程
    struct binder_transaction *to_parent; //上一个binder_transaction, 用于server端
    unsigned need_reply:1;
    /* unsigned is_dead:1; */    /* not used at the moment */

    struct binder_buffer *buffer;
    unsigned int    code;
    unsigned int    flags;
    long    priority;
    long    saved_priority;
    kuid_t    sender_euid;
};

 

5. binder_thread

binder_proc里的threads 红黑树存放着指向binder_thread对象的指针。这里的binder_thread 不只仅包括service的binder thread, 也包括访问其余service的调用thread. 也就是说全部与binder相关的线程都会在binder_proc的threads红黑树里留下记录。binder_thread里最重要的两个成员变量是 transaction_stack 和 wait.

struct binder_thread {
    struct binder_proc *proc;
    struct rb_node rb_node; //红黑树节点
    int pid;
    int looper;  //
    struct binder_transaction *transaction_stack; //transaction栈
    struct list_head todo;
    uint32_t return_error; 
    uint32_t return_error2; 
    wait_queue_head_t wait; //等待队列,用于阻塞等待
    struct binder_stats stats;
};

在binder_proc里面咱们也能看到一个wait 队列,是否是意味着线程既能够在proc->wait上等待,也能够在thread->wait上等待?binder driver 对此有明确的用法,全部的binder threads (server 端)都等待在proc->wait上。由于对于服务端来讲,用哪一个thread来响应远程调用请求都是同样的。然而全部的ref thread(client端)的返回等待都发生在调用thread的wait 队列,由于,当某个binder thread 完成服务请求后,他必须唤醒特定的等待返回的线程。可是有一个例外,在双向调用的状况下,某个Server端的thread将会挂在thread->wait上等待,而不是proc->wait. 举个例子,假设两个进程P1 和 P2,各自运行了一个Service, S1,S2, P1 在 thread T1 里调用S2提供的服务,而后在T1->wait里等待返回。S2的服务在P2的binder thread(T2)里执行,执行过程当中,S2又调到S1里的某个接口,按理S1 将在P1的binder thread T3里执行, 若是P1接下来又调到了P2,那又会产生新的进程 T4, 若是这个反复调用栈很深,须要耗费大量的线程,显然这是很是不高效的设计。因此,binder driver 里作了特殊的处理。当T2 调用 S1的接口函数时,binder driver 会遍历T2的transaction_stack, 若是发现这是一个双向调用(binder_transaction->from->proc 等于P1), 便会唤醒正在等待reply的T1,T1 完成这个请求后,继续等待S2的回复。这样,只须要最多两个Thread就能够完成多层的双向调用。

binder_thread里的transaction_stack 是用链表实现的堆栈, 调用线程和服务线程的transaction有着不一样的堆栈。下图是上面这个例子的堆栈情形:

 

6. binder_ref_death

binder_ref 记录了从client进程到server进程某个service的引用,binder_ref_death 是binder_ref的一个成员变量,它的不为空说明了client进程想获得这个service的死亡通知(严格意义上讲,是service所在进程的死亡通知,由于一个进程一个/dev/binder的fd, 只有进程死亡了,driver才会知晓,经过 file_operations->release 接口)。

struct binder_ref_death {
    struct binder_work work;
    binder_ptr __user cookie;
};

 

咱们能够下面一张时序图来了解binder death notifycation 的全过程。

 

7. binder_work

从应用程序角度来看,全部的binder调用都是同步的。但在binder driver 内部,两个进程间的交互都是异步的,一个进程产生的请求会变成一个binder_work, 并送入目标进程或线程的todo 队列里,而后唤醒目标进程和线程来完成这个请求,并阻塞等待结果。binder_work的定义以下:

struct binder_work {
    struct list_head entry;
    enum {
        BINDER_WORK_TRANSACTION = 1,
        BINDER_WORK_TRANSACTION_COMPLETE,
        BINDER_WORK_NODE,
        BINDER_WORK_DEAD_BINDER,
        BINDER_WORK_DEAD_BINDER_AND_CLEAR,
        BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
    } type;
};

 

很简单,其实只定义了一个链表的节点和work的类型。

8. binder_buffer

进程间通讯除了命令,还有参数和返回值的交换,要将数据从一个进程的地址空间,传到另一个进程的地址空间,一般须要两次拷贝,进程A -> 内核 -> 进程B。binder_buffer 就是内核里存放交换数据的空间(这些数据是以Parcel的形式存在)。为了提升效率,Android 的 binder 只须要一次拷贝,由于binder 进程经过mmap将内核空间地址映射到用户空间,从而能够直接访问binder_buffer的内容而无需一次额外拷贝。binder_buffer由内核在每次发起的binder调用建立,并赋给binder_transaction->buffer. binder driver 根据binder_transaction 生产 transaction_data(包含buffer的指针而非内容), 并将其复制到用户空间。

9. flat_binder_obj

前面咱们说过,<proc, handle> 能够标识一个BpBinder 对象,而<proc, ptr> 能够标识一个BBinder对象。Binder Driver 会收到来自与BpBinder 和 BBinder的系统调用,它是如何判别它们的身份呢?答案就在flat_binder_obj里,先看看它的定义,

struct flat_binder_object {
 unsigned long type;  //见下面定义
 unsigned long flags;
 union {
 void *binder;            //BBinder,经过它driver能够找到对应的node
 signed long handle; //BpBinder,根据它driver能够找到对应的ref
 };
 void *cookie;
};

enum {
 BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
 BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
 BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
 BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
 BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
};

union代表了在Server端和Client端它有着不一样的解读。type则代表了它的身份。binder driver 根据它能够找到BpBinder 和 BBinder 在内核中相对应的对象 (ref 或 node). flat_binder_obj 封装在parcel里,详见Parcel.cpp.

至此,binder driver里面重要的数据结构都介绍完了,你们对binder driver的工做原理也有了大体的了解,这里再稍做总结:

1.  当一个service向binder driver 注册时(经过flat_binder_object), driver 会建立一个binder_node, 并挂载到该service所在进程的nodes红黑树。

2.  这个service的binder线程在proc->wait 队列上进入睡眠等待。等待一个binder_work的到来。

3.  客户端的BpBinder 建立的时候,它在driver内部也产生了一个binder_ref对象,并指向某个binder_node, 在driver内部,将client和server关联起来。若是它须要或者Service的死亡状态,则会生成相应的binfer_ref_death.

4.  客户端经过transact() (对应内核命令BC_TRANSACTION)请求远端服务,driver经过ref->node的映射,找到service所在进程,生产一个binder_buffer, binder_transactionbinder_work 并插入proc->todo队列,接着唤醒某个睡在proc->wait队列上的Binder_thread. 与此同时,该客户端线程在其线程的wait队列上进入睡眠,等待返回值。

5.  这个binder thread 从proc->todo 队列中读出一个binder_transaction, 封装成transaction_data (命令为 BR_TRANSACTION) 并送到用户空间。Binder用户线程唤醒并最终执行对应的on_transact() 函数。

6.  Binder用户线程经过transact() 向内核发送 BC_REPLY命令,driver收到后从其thread->transaction_stack中找到对应的binder_transaction, 从而知道是哪一个客户端线程正在等待这个返回。

7.  Driver 生产新的binder_transaction (命令 BR_REPLY), binder_buffer, binder_work, 将其插入应用线程的todo对立,并将该线程唤醒。

8.  客户端的用户线程收到回复数据,该Transaction完成。

9.  当service所在进程发生异常退出,driver 的 release函数被调到,在某位内核work_queue 线程里完成该service在内核态的清理工做(thread,buffer,node,work...), 并找到全部引用它的binder_ref, 若是某个binder_ref 有不为空的binder_ref_death, 生成新的binder_work, 送人其线程的todo 对立,唤醒它来执行剩余工做,用户端的DeathRecipient 会最终被调用来完成client端的清理工做。

下面这张时序图描述了上述一个transaction完成的过程。不一样的颜色表明不一样的线程。注意的是,虽然Kernel和User space 线程的颜色是不同的,但全部的系统调用都发生在用户进程的上下文里(所谓上下文,就是Kernel能经过某种方式找到关联的进程(经过Kernel的current 宏),并完成进程相关的操做,好比说唤醒某个睡眠的线程,或跟用户空间交换数据,copy_from, copy_to, 与之相对应的是中断上下文,其彻底异步触发,所以没法作任何与进程相关的操做,好比说睡眠,锁等)。

 

 

4. Java Binder

Binder 的学习已经接近尾声了,咱们已经研究了Binder Driver, C/C++的实现,就差最后一个部分了,Binder在Java端的实现了。Java端的实现与Native端相似,咱们用下面的表格和类图归纳他们的关系

Native Java Note
IBinder IBinder  
IInterface IInterface  
IXXX IXXX aidl文件定义
BBinder Binder  经过JavaBBinder类做为桥梁
BpBinder BinderProxy  经过JNI访问Native的实现
BnInterface N/A  
BpInterface   N/A  
BnXXX Stub aidl工具自动生成   
BpXXX     Proxy aidl工具自动生成 
     

 

 

 

 

 

 

 

 

 

 

可见,Java较Native端实现简单不少,经过Aidl工具来实现相似功能。因此,要实现一个Java端的service,只须要作如下几件事情:

1. 写一个.aidl文件,里面用AIDL语言定义一个接口类IXXX。

2.在Android.mk里加入该文件,这样编译系统会自动生成一个IXXX.java, 放在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core 下面。

3. 在服务端,写一个类,扩展IXXX.Stub,具体实现IXXX的接口函数。

相关文章
相关标签/搜索