天天看点

Android Binder Native

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

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

由上图可知:

  • 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 >= ) {
       mVMStart=mmap(,BINDER_VM_SIZE,PROT_READ,MAP_PRIVATE | MAP_NORESERVE, mDriverFD, );   

        if (mVMStart == MAP_FAILED) { 
           close(mDriverFD);
            mDriverFD = -;
        }
    }

}
           

在上面代码中,我们看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 >= ) {
 ....
 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();
        }
    }

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

可以看到这里直接调用了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 == ) {
            .....
            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()
    , mObitsSent()
    , 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 = ;

virtual sp<IBinder> checkService( const String16& name) const = ;

virtual status_t   addService( const String16& name,
const sp<IBinder>& service,  bool allowIsolated = false) = ;

virtual Vector<String16>    listServices() = ;
.....
};
           

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

前面说到过,如何与BpBinder和BBinder关联上? 实际则是通过DECLARE_META_INTERFACE和IMPLEMENT_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

它在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相关类的关系。

Android Binder Native

在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 = ;
        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(),
      mLastTransactionBinderFlags()
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity();
    mOut.setDataCapacity();
}
           

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_开头。

status_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 = ; 
    //handle为,表示目的端ServiceManager
    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = ;
    tr.sender_pid = ;
    tr.sender_euid = ;
    .....
    .....
    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 () { 
       //注意talkWithDriver
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == ) 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();
    }

    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接收后 如何处理,请大家自定去分析~~~链接上面已给。

Android Binder Native