[Binder学习篇二:俯瞰Binder] Android Binder机制[转]

1. Binder 通信概述

  Binder通信是一种Client-Server的通信结构,

  1. 从表面上看,是Client通过获得一个Server的代理接口,对Server进行直接调用;

  2. 实际上,代理接口中定义的方法与Server中定义的方法是一一对应的;

  3. Client调用某个代理接口中的方法时,代理接口的方法会将Client传递的参数打包为Parcel对象;

  4. 代理接口将Parcel发送给内核中的Binder Driver;

  5. Server会读取Binder Driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;

  6. 整个的调用过程是一个同步过程,在Server处理的时候,Client会被Block住。

                              

2. Service Manager

  Service Manager是一个linux级的进程,顾名思义,就是Service的管理器。这里的Service是什么概念呢?这里的Service的概念和init过程中init.rc中的Service是不同的,init.rc中的Service都是Linux进程,但是这里的Service它并不一定是一个进程,也就是说可能多个Service属于同一个Linux进程。本文中,如不加特殊说明均指Android native端的Service。

  任何Service在被使用之前,均要向SM(Service Manager)注册,同时客户端需要访问某个Service时,应该首先向SM查询是否存在该服务,如果SM存在这个Service,那么会将该Service的handle返回给Client,handle是每个Service的唯一标识符。

  

/* Android4.3-Code/frameworks/native/cmds/servicemanager/service_manager.c */

int main(int argh, char **argv)
{
  struct binder_state *bs;
   void *svcmgr = BINDER_SERVICE_MANAGER;  
  /*
Android4.3-Code/frameworks/native/cmds/servicemanager/binder.h :
   * #define BINDER_SERVICE_MANAGER ((VOID *)0)
  */
  bs = binder_open(128*1024);
  
  if (binder_become_context_manager(bs)) {
    ALOGE("cannot become context manager (%s)\n", strerror(errno));
    return -1;
  }

  svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
  return 0; }

  这个进程的主要工作如下:

    1. 初始化Binder,打开设备/dev/binder设备,在内存中为binder映射128K字节空间(Binder本质为ShareMemory);

    2. 指定SM对应的代理binder的handle为0,当Client尝试与SM通信时,需要创建一个handle为0的代理Binder,这里的代理Binder其实就是第一节中描述的那个代理接口;

    3. 通知Binder Driver(BD)使SM成为BD的context manager;

    4. 维护一个死循环,在这个死循环中,不停地去读取内核中BD,查看是否有可读的内容;即是否具有对Service的操作请求,如果有,则调用svcmgr_handler回调来处理请求的操作;

    5. SM维护了一个svclist列表来存储service的信息。

  这里需要声明一下,当Service在向SM注册时,该Service就是一个Client,而SM则作为Server。当某个进程需要与该Service通信时,此时这个进程为Client,Service作为Server。因此Service不一定为Server,有时它也是作为Client存在的。

  应用和Service之间的通信会涉及到2次Binder通信:

    1. 应用向SM查询Service是否存在,如果存在则获得该Service的代理Binder,此为一次Binder通信;

    2. 应用通过代理Binder调用Service的方法,此为第二次Binder通信。

3. ProcessState

  ProcessState是以单例模式设计的。每个进程在使用Binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在Binder通信时的状态。

  ProcessState有如下两个功能:

    1. 创建一个Thread,该线程负责与内核中的Binder模块进行通信,该线程称为Pool Thread;

    2. 为指定的Handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

3.1 Pool Thread

  在Binder IPC中,所有的进程均会启动一个Thread来负责与BD来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍。

/*
 * Pool Thread 启动方式
*/
ProcessState::self()->startThreadPool();

 

3.2 BpBinder获取

  BpBinder主要功能是负责Client向BD发送调用请求的数据。它是Client端Binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据。

  BpBinder会将当前通信中的server的handle记录下来,当有数据发送时,会通知BD数据发送的目标。

  ProcessState通过如下方式来获取BpBinder对象:

/*
 * ProcessState获取BpBinder的方式 
*/
ProcessState::self()->getContextObject(handle);

  在这个过程中,ProcessState会维护一个BpBinder的Vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,会去查询mHandleToObject,如果对应的handle已经有Binder指针,那么不再创建,否则创建Binder并插入到mHandleToObject中。

  ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个Client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,Client会创建一个代理接口BpServiceManager。

4. IPCThreadState

  IPCThreadState是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool Thread,也就是说每一个进程只会启动一个Pool Thread,因此每个进程只需要一个IPCThreadState即可。

  Pool Thread的实际内容为:

/*
 * PoolThread
*/
virtual bool threadLoop()
{
  IPCThreadState::self()->joinThreadPool(mIsMain);
  return false;    
}

  ProcessState有两个Parcel成员,mIn和mOut,Pool Thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn中,同时不停的检查mOut是否有数据需要向BD发送,如果有,将其内容写到BD中。总之:从BD中读出的数据保存到mIn,待写入到BD中的数据保存到mOut中。

  IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。

 

 

posted @ 2016-07-04 10:49  若离相惜  阅读(536)  评论(0)    收藏  举报