Android Binder Native

来源:互联网 发布:米拉奇战记无敌版软件 编辑:程序博客网 时间:2024/05/22 16:00

我们要知道,Android系统基本上可以看做是一个基于Binder通信的C/S架构,Binder把Android系统的各个部分都连在了一起,所以它的重要不可言喻,我们有必要掌握好它。

Binder是Android系统提供的一种 “ 进程间通信(IPC)” 机制。在基于Binder的C/S**(Client、Service)架构中除了 **ClientService端外、Android还有一个ServiceManager,它管理系统中的各种服务。

Created with Raphaël 2.1.0ServerServerServiceManagerServiceManagerClientClient1.Server向ServiceManager注册服务2.Client向ServiceManager查询服务3.Client使用Server


由上图可知:

  • Server进程要先注册一些Service到ServiceManager中,所以Server是ServiceManager的客户端.
  • 如果某个Client进程要使用Server,则必须先去ServiceManager去查询服务,所以Client是ServiceManager的客户端
  • Client根据得到的Service信息与Service所载的Server进程建立通信线路,然后就可以和Service交互了,所以Client是Service的客户端

我们要分析Binder,必然要以一个入口来分析它,由于我没有自行分析过C层代码,所以就按照我所学的来,用MediaServer来打开我们的Binder之路。

以下代码使用在线阅读网站:http://androidxref.com/进行阅读,且代码版本为 7.1.1_r6

MediaServer(main_mediaserver.cpp)

源码位置:
1. 4.0.x版本路径
2. 4.0.x以上版本

Notice:以下代码省略了大部分与分析无关的代码。

分析:
进入main_dediaserver.cpp中我们可以看见,内部只有一个main方法

int main(int argc __unused, char **argv __unused){    sp<ProcessState> proc(ProcessState::self());    sp<IServiceManager> sm(defaultServiceManager());    MediaPlayerService::instantiate();    ProcessState::self()->startThreadPool();   IPCThreadState::self()->joinThreadPool(); }

上面操作总共分为5部分。
1. 获得一个ProcessState实例
2. 获取一个IServiceManager
3. 多媒体系统MediaPlayer服务
4. 创建线程池
5. 将自己加入线程池中

由上面5部分我们进行代码分析..

ProcessState::self

ProcessState::self()

进入ProcessState的self方法 ProcessState.cpp

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

看上面代码得知,如果gProcess不等于null,那么直接返回。 否则新建一个ProcessState 并赋值给gProcess 然后返回。由代码可知,self采用了单例模式,说明了每个进程中只能有一个ProcessState。 下面进入ProcessState构造

ProcessState::ProcessState()    : mDriverFD(open_driver())    , mVMStart(MAP_FAILED)    .......    ......{    if (mDriverFD >= 0) {       mVMStart=mmap(0,BINDER_VM_SIZE,PROT_READ,MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);           if (mVMStart == MAP_FAILED) {            close(mDriverFD);            mDriverFD = -1;        }    }}

在上面代码中,我们看open_driver()
open_driver():该函数的作用是 用来打开/dev/binder 这个设备,它是Android在内核中用来完成进程间通信的一个虚拟设备.
mmap():BINDER_VM_SIZE =(1*1024*1024) -(4096*2) =1M-8k,该函数实现后,binder驱动会分配一块内存区域来接收数据

static int open_driver(){int fd = open("/dev/binder", O_RDWR | O_CLOEXEC); if (fd >= 0) { .... size_t maxThreads = DEFAULT_MAX_BINDER_THREADS; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); .... } return fd;}

上面代码做了2件事
1. 打开binder设备
2. 通过ioctl的方式告诉binder驱动,该fd最大支持线程数

所以由ProcessState::self可知:

  • ProcessState进程唯一
  • 打开了/dev/binder 虚拟设备
  • 打开后使用mmap,Binder驱动会分配一块内存接收数据

defaultServiceManager

defaultServiceManager返回的是一个IServiceManager对象,通过它我们可以与别的进程的ServiceManager进行交互。
下面分析代码 IServiceManager.cpp

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

看代码可知,是个单例,接着调用了3个方法来获取gDefaultServiceManager.
1. 先获取ProcessState实例
2. 调用ProcessState的getContextObject函数,注意参数为NULL
3. 把getContextObject返回的变量作为interface_case参数调用

首先来看getContextObject ProcessState.cpp

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

可以看到这里直接调用了getStrongProxyForHandle(0).. 注意传入的是个0..并返回了IBinder

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){    sp<IBinder> 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) {            .....            b = new BpBinder(handle);            e->binder = b;            if (b) e->refs = b->getWeakRefs();           result = b;   }   return result;}
  1. lockupHandleLocked:该函数参数handle代表的意义为索引,根据索引去一个资源数组里面去寻找资源,如果没有则创建一个新的项并返回。
  2. 对于新创建的资源, binder为null,所以进入分支,然后创建BpBinder,并赋值handle_entry 的binder, 最后赋值给result.
  3. 返回BpBinder(handle), handle的值为0.

BpBinder是什么?

IPC内重要部分其中就是BpBinder,实现了IBinder类。
IBinder 有两个实现类,分别是 BpBinder、BBinder。

  • BpBinder是客户端用来与服务端交互的代理类,p 译为proxy
  • BBinder则是服务端.

    BpBinder 与BBinder是一一对应的。

    BpBinder.cpp

    BpBinder::BpBinder(int32_t handle): mHandle(handle), mAlive(1), mObitsSent(0), mObituaries(NULL){extendObjectLifetime(OBJECT_LIFETIME_WEAK);IPCThreadState::self()->incWeakHandle(handle);}

由上面代码我们看到了一个IPCThreadState,它是什么?

现在我们知道了getContextObject() 实际染回的是一个BpBinder(0)对象,那么代码就变成了interface_cast(new BpBinder(0));

interface_cast是什么? 我们可以在IInterface.h内查看它的定义.

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

可以看到这相当于一个模版,根据传进来的泛型来调用泛型类所对应的方法,那么我们可以接着看IServiceManager::asInterface(new BpBinder(0)).

我们想象一下,BpBinder和BBinder是用于通信的,那么如何和这些东西关联上?答案就是通过IServiceManager,下面看IServiceManager的定义
IServiceManager.h

class IServiceManager : public IInterface{public:DECLARE_META_INTERFACE(ServiceManager);....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) = 0;virtual Vector<String16>    listServices() = 0;.....};

需要注意的是 DECLARE_META_INTERFACE(ServiceManager),其余则是提供给ServiceManager的一些方法.

前面说到过,如何与BpBinder和BBinder关联上? 实际则是通过DECLARE_META_INTERFACEIMPLEMENT_META_INTERFACE 这两个宏来关联的。它们两个的定义在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();  

DECLARE_META_INTERFACE(ServiceManager) 把ServiceManager替换得到下面这样。

static const android::String16 descriptor;                          static android::sp<IServiceManager> asInterface(const android::sp<android::IBinder>& obj); virtual const android::String16& getInterfaceDescriptor() const;    IServiceManager();                                                     virtual ~IServiceManager();  

由名字可知,DECLARE 为定义,那么IMPLEMENT肯定为实现了。原始宏就不贴代码了,跟上面一个套路。我们来看看它的实际使用。
IServiceManager.cpp

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

它在IServiceManager.cpp 中的最后一行代码,经过Interface.h宏定义的模版转换后,那么就变成下面的样子

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                           const android::String16 IServiceManager::descriptor("android.os.IServiceManager");                 const android::String16&                                                        IServiceManager::getInterfaceDescriptor() const {                      return IServiceManager::descriptor;                                    }                                                                       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);                                      }                                                                  }                                                                     return intr;                                                        }                                                                       IServiceManager::IServiceManager() { }                                        IServiceManager::~IServiceManager() { }       

现在我们知道了,interface_cast 《IServiceManager》(new BpBinder(0)),最后是调用了 IServiceManager::asInterface(new BpBinder(0)),最后把BpBinder(0)作为参数 来创建BpServiceManager

BpServiceManager是什么?要明白这个问题,我们先来了解一下IServiceManager相关类的关系。
这里写图片描述

在BpServiceManager的构造内 会调用BpInterface构造,并把参数传递,最后会赋值给BpRefBase的 mRemote, 到这,就和BpBinder联系上了。
到这里 defaultServiceManager分析完成,它主要完成了以下工作。

  • 创建了一个BpBinder对象,handle值为0
  • 创建了一个BpServiceManager 并把 BpBinder赋值给mRemote

知道了通信层是如何工作的,那么业务层是怎样的?我们通过MediaPlayerService来分析一下。

MediaPlayerService::instantiate();

void MediaPlayerService::instantiate() {    defaultServiceManager()->addService(String16("media.player"), new MediaPlayerService());}

defaultServiceManager 返回BpManagerService.

  virtual status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated){          Parcel data, reply;            data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());        data.writeString16(name);        data.writeStrongBinder(service);        data.writeInt32(allowIsolated ? 1 : 0);        status_t        err=remote()>transact(ADD_SERVICE_TRANSACTION, data, &reply);        return err == NO_ERROR ? reply.readExceptionCode() : err;    }

把Parcel数据包打包 并传给BpBinder的transact函数.

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

可以看到,实际上BpBinder只是个工具!!! 实际操作的是IPCThreadState。

下面分析IPCThreadState.cpp

IPCThreadState* IPCThreadState::self(){    if (gHaveTLS) {restart:        const pthread_key_t k = gTLS;        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);        if (st) return st;        return new IPCThreadState;    }     goto restart;}

gTLS: TLS为(Thread Local Storage)简称,为线程本地存储空间,每个线程都有一个,pthread_getspecific 从TLS内获取IPCThreadState,如果有就返回,没有就创建一个。

IPCThreadState::IPCThreadState()    : mProcess(ProcessState::self()),      mMyThreadId(gettid()),      mStrictModePolicy(0),      mLastTransactionBinderFlags(0){    pthread_setspecific(gTLS, this);    clearCaller();    mIn.setDataCapacity(256);    mOut.setDataCapacity(256);}

IPCThreadState构造内调用pthread_setspecific 把自己设置进去,并设置mIn,mOut缓冲区(两个Parcel) 用来接收和发送数据。

status_t IPCThreadState::transact(int32_t handle,                                  uint32_t code, const Parcel& data,                                  Parcel* reply, uint32_t flags){    status_t err = data.errorCheck();    ....    if (err == NO_ERROR) {        ...        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);    }        ...    if (reply) {            err = waitForResponse(reply);        } else {            Parcel fakeReply;            err = waitForResponse(&fakeReply);        }    .....    return err;}

BC_TRANSACTION 是应用程序向Binder设备发送消息的消息码,binder设备回复信息以BR_开头。

5status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer){    binder_transaction_data tr;    tr.target.ptr = 0;     //handle0,表示目的端ServiceManager    tr.target.handle = handle;    tr.code = code;    tr.flags = binderFlags;    tr.cookie = 0;    tr.sender_pid = 0;    tr.sender_euid = 0;    .....    .....    mOut.writeInt32(cmd);    mOut.write(&tr, sizeof(tr));    return NO_ERROR;}

最后把命令写到mOut中,接下来走writeForResponse

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){    uint32_t cmd;    int32_t err;       while (1) {        //注意talkWithDriver        if ((err=talkWithDriver()) < NO_ERROR) break;        err = mIn.errorCheck();        if (err < NO_ERROR) break;        if (mIn.dataAvail() == 0) continue;        cmd = (uint32_t)mIn.readInt32();        switch(cmd){        .....        default:           err = executeCommand(cmd);         break;       }       ....       return err;

假设我们发送后,马上得到了回复,然后我们看executeCommand(cmd),其内根据一些binder设备 返回的 以BR开头的码来做不同的事情。

status_t IPCThreadState::executeCommand(int32_t cmd){    BBinder* obj;    RefBase::weakref_type* refs;    status_t result = NO_ERROR;    switch ((uint32_t)cmd) {      case BR_ERROR:        result = mIn.readInt32();          break;      ....      case BR_TRANSACTION:        {        ....        ....        if (tr.target.ptr) {                ....         error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);         reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);                ....                }            } else {                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);            }        }          break;

上面把tr.cookie转成了BBinder,它的实际对象是BnServiceManager,我们来看BBinder的transaction.

status_t BBinder::transact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    data.setDataPosition(0);    status_t err = NO_ERROR;    switch (code) {        case PING_TRANSACTION:            reply->writeInt32(pingBinder());            break;        default:            err = onTransact(code, data, reply, flags);            break;    }    if (reply != NULL) {        reply->setDataPosition(0);    }    return err;}

这里的onTransact函数会调用到BBinder子类的onTransact,然后子类进行处理。可以在这里 查看onTransact函数,知道这一处,别的都一样。

发送请求是在talkWithDriver内,这里就不贴代码了。其内主要是用ioctl方式来发送请求。到这为止,发送与接收就告一段落了继续分析下面。

startThreadPool

void ProcessState::startThreadPool(){    AutoMutex _l(mLock);    //如果已经 startThreadPool过,则略过    if (!mThreadPoolStarted) {        mThreadPoolStarted = true;        spawnPooledThread(true);// 这里为true    }}
void ProcessState::spawnPooledThread(bool isMain){    if (mThreadPoolStarted) {        String8 name = makeBinderThreadName();        sp<Thread> t = new PoolThread(isMain);        t->run(name.string());    }}

PoolThread是ProcessState内 Thread的一个子类

class PoolThread : public Thread{public:    PoolThread(bool isMain)        : mIsMain(isMain)    {    }protected:    virtual bool threadLoop()    {        IPCThreadState::self()->joinThreadPool(mIsMain);        return false;    }    const bool mIsMain;};

接着调用了IPCThreadState的joinThreadPool方法.

void IPCThreadState::joinThreadPool(bool isMain){   //如果为true 则循环处理,把信息写到mOut内    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);    set_sched_policy(mMyThreadId, SP_FOREGROUND);    status_t result;    do {        //处理已经死亡的BBinder         processPendingDerefs();        result = getAndExecuteCommand();        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {            .....            mProcess->mDriverFD, result);            abort();        }        if(result == TIMED_OUT && !isMain) {            break;        }    } while (result != -ECONNREFUSED && result != -EBADF);     (void*)pthread_self(), getpid(), (void*)result);    mOut.writeInt32(BC_EXIT_LOOPER);    talkWithDriver(false);}

在getAndExecuteCommand内 又调用了talkWithDriver 发送请求给binder,和executeCommand 接收回复的方法。

所以由以上代码可知,主线程,和startThreadPool的线程 分别在读取binder设备,查看是否有请求。

到这里,我们应该大体明白了Binder的流程。
1. 创建BpBinder(0)
2. 创建BpServiceManager(BpBinder(0)),在BpServiceManager内,把BpBinder赋值给了mRemote,至此业务层关联了BpBinder
3. 注册服务,调用BpServiceManager的addService函数,在其内调用 BpBinder的transact.
4. 创建IPCThreadState并调用 它的transact,传入的参数mHandler为0,用户标示目的地的服务端(ServiceManager).
5. 在transact内的waitForResponse内 while(1){来发送,等待接收binder消息}
6. 在while(1){}内 的executeCommand内的 case BR_TRANSACTION:内 获取了BBinder 然后调用其 transact.
7. BBinder 的transact调用了子类的 onTransact函数.

至此消息发送到了服务端的onTransact函数,完成了进程间通信(IPC)

疑问 , 谁是BBinder的子类 用来接收onTransact函数。?

答案是ServiceManager来做这些工作的。

可以说,如果想要进程间通信,则必须向ServiceManager注册服务,然后客户端通过向ServiceManager查询 获取到的Server 来进行响应处理。

有关于ServiceManager从onTransact接收后 如何处理,请大家自定去分析~~~链接上面已给。

Binder

原创粉丝点击