Android Binder机制(1501210451 张志康)

来源:互联网 发布:2016年3月非农数据 编辑:程序博客网 时间:2024/06/03 16:10

本文主要分析native层和Java层的Android binder通信机制。

binder是Android最为常见的进程通信机制之一,其驱动和通信库是binder的核心,分别由C和C++编写,应用程序通过JNI同底层库进行关联,也就是native层驱动和通信库通过Java层包装后被Java层调用。

源代码网址:http://androidxref.com/4.2_r1/

参考博客:http://blog.csdn.net/coding_glacier/article/details/7520199

一、native层整体通信流程

  • 通信流程概要

    在探究binder通信流程之前,首先我们需要了解Binder机制的四个组件:Client、Server、Service Manager和Binder驱动程序。关系如图:

    应用程序最终目的是完成Client组件和Server组件之间的通信。ServiceManger对于大家而言是一个公共接入点,0便是ServiceManger的句柄值。

    从表面看通信建立的流程便是注册和获取的过程: 1、client通过参数(Parcel包)传递进行通信请求;

    2、在收到通信请求时,Server组件需要通过0这个句柄值访问ServiceManger,在ServiceManger中注册一个binder实体。并关联一个字符串;

    3、Client组件通过0这个标识去访问ServiceManger,通过一个字符去查询Server组件的引用,此ServiceManger将Server注册的binder实体的一个引用传递给Client端,此时client便可根据这个引用同server进行通信了。

    由以上可知,在收到请求时server将一个binder实体传递给C进程,而client得到的只是binder的一个引用,进而调用binder实体的函数。BpBinder和BBinder分别代表binder 的引用和实体,它们均继承自IBinder类。

    在描述具体流程之前我们先来了解binder通信中需要用到的三个主要基类:

    1.基类IInterface: 为server端提供接口,它的子类声明了service能够实现的所有的方法;

    2.基类IBinder BBinder与BpBinder均为IBinder的子类,因此可以看出IBinder定义了binder IPC的通信协议,BBinder与BpBinder在这个协议框架内进行的收和发操作,构建了基本的binder IPC机制。

    3.基类BpRefBase client端在查询SM获得所需的的BpBinder后,BpRefBase负责管理当前获得的BpBinder实例。

  • ServiceManger

    首先我们来了解一下在通信流程中ServiceManger所做的工作。

    ServiceManger是一个linux级进程,是一个service管理器(service向SM注册是,service就是一个client,而ServiceManger便是server),即我们前边提到的:每一个service被使用之前,均要向ServiceManger注册,客户端通过查询ServiceManger是否存在此服务来获取service的handle(标识符)。

      ServiceManger入口函数为:service_manager.c  位于:/frameworks/base/cmds/servicemanager/  int main(int argc, char **argv)  {      struct binder_state *bs;      void *svcmgr = BINDER_SERVICE_MANAGER;      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映射128Kb空间。  bs = binder_open(128*1024);  其中binder_open位于binder.c中,源代码为:  struct binder_state *binder_open(unsigned mapsize)  {      struct binder_state *bs;      bs = malloc(sizeof(*bs));      if (!bs) {          errno = ENOMEM;          return 0;      }      bs->fd = open("/dev/binder", O_RDWR);      ……      return 0;  }      2. 指定SM对于代理binder的handle为0,即client尝试同SM通信时创建一个handle为0的代理binder。  void *svcmgr = BINDER_SERVICE_MANAGER;  svcmgr_handle = svcmgr;  其中BINDER_SERVICE_MANAGER在binder.h中被指定为0:  #define BINDER_SERVICE_MANAGER ((void*) 0)      3. 通知binder driver(BD)使SM成为BD的context manager;  if (binder_become_context_manager(bs)) {  LOGE("cannot become context manager (%s)/n", strerror(errno));  return -1;  }  binder_become_context_manager(bs)源码位于binder.c中:      int binder_become_context_manager(struct binder_state *bs)  {      return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);  }      4.进入一个死循环,不断读取内核的binder    driver,查看是否有对service的操作请求,如果有调用svcmgr_handler来处理请求操作:  binder_loop(bs, svcmgr_handler);  binder_loop(,)源码位于binder.c中:  void binder_loop(struct binder_state *bs, binder_handler func)  {      int res;      struct binder_write_read bwr;      unsigned readbuf[32];      ……      }  }      5.维护一个svclist列表来存储service的信息。      源码位于service_manager.c:  int svcmgr_handler(struct binder_state *bs,                     struct binder_txn *txn,                     struct binder_io *msg,                     struct binder_io *reply)  {      struct svcinfo *si;      ……  }

  • ProcessState

    ProcessState是每个进程在使用Binder通信时都需要维护的,用来描述当前进程的binder状态。

    ProcessState主要完成两个功能:

    1.创建一个thread负责与内核中的binder模块进行通信(Poolthread)。

    在Binder IPC中,所有进程均会启动一个thread来负责与binder来直接通信,也就是不断读写binder,这个线程主体是一个IPCThreadState对象(具体介绍见第4节)。

          Poolthread启动方式:ProcessState::self()->startThreadPool();  /frameworks/native/libs/binder/ProcessState.cpp  136void ProcessState::startThreadPool()  {      AutoMutex _l(mLock);  `   if (!mThreadPoolStarted) {          mThreadPoolStarted = true;          spawnPooledThread(true);      }  }

    2.为知道的handle创建一个BpBinder对象,并管理进程中所有的BpBinder对象。

    BpBinder在第一节已经提到,其主要功能是负责client向BD发送调用请求的数据,是client端binder通信的核心,通过调用transact向BD发送调用请求的数据。

    ProcessState通过如下函数获取BpBinder对象:

          /frameworks/native/libs/binder/ProcessState.cpp      sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)  {      return getStrongProxyForHandle(0);  }  sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)  {      sp<IBinder> result;      AutoMutex _l(mLock);      handle_entry* e = lookupHandleLocked(handle);  ……      return result;  }  ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)  {      const size_t N=mHandleToObject.size();      if (N <= (size_t)handle) {          handle_entry e;          e.binder = NULL;          e.refs = NULL;          status_t err = mHandleToObject.insertAt(e, N, handle+1-N);          if (err < NO_ERROR) return NULL;      }      return &mHandleToObject.editItemAt(handle);  }

    在获取BpBinder对象的过程中,ProcessState会维护一个BpBinder的vecto:mHandleToObject(具体调用过程见上述源代码)。

    创建一个BpBinder实例时,回去查询mHandleToObject,如果对应的handler以及有binder指针,就不再创建,否则创建并插入到mHandlerToObject中(具体代码见上述的lookupHandleLocked)。

    BpBinder构造函数位于/frameworks/native/libs/binder/BpBinder.cpp:

          BpBinder::BpBinder(int32_t handle)      : mHandle(handle)      , mAlive(1)      , mObitsSent(0)      , mObituaries(NULL)  {      ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);      extendObjectLifetime(OBJECT_LIFETIME_WEAK);      IPCThreadState::self()->incWeakHandle(handle);  }

    通过此构造函数我们可以发现:BpBinder会将通信中server的handle记录下来。当有数据发送时,会把数据的发送目标通知BD。

  • IPCThreadState

    IPCThreadState也是一个单例模式,由上边我们已知每个进程维护一个ProcessState实例,且ProcessState只启动一个Pool thread,因此一个进程之后启动一个Pool thread。

    IPCThreadState实际内容为:

      void IPCThreadState::joinThreadPool(bool isMain)  {      LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());      mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);              set_sched_policy(mMyThreadId, SP_FOREGROUND);       status_t result;      do {          int32_t cmd;          if (mIn.dataPosition() >= mIn.dataSize()) {              size_t numPending = mPendingWeakDerefs.size();              if (numPending > 0) {                  for (size_t i = 0; i < numPending; i++) {                      RefBase::weakref_type* refs = mPendingWeakDerefs[i];                      refs->decWeak(mProcess.get());                  }                  mPendingWeakDerefs.clear();              }              numPending = mPendingStrongDerefs.size();              if (numPending > 0) {                  for (size_t i = 0; i < numPending; i++) {                      BBinder* obj = mPendingStrongDerefs[i];                      obj->decStrong(mProcess.get());                  }                  mPendingStrongDerefs.clear();          }          }          result = talkWithDriver();          if (result >= NO_ERROR) {              size_t IN = mIn.dataAvail();              if (IN < sizeof(int32_t)) continue;              cmd = mIn.readInt32();              IF_LOG_COMMANDS() {                  alog << "Processing top-level Command: "                      << getReturnString(cmd) << endl;              }              result = executeCommand(cmd);          }          if(result == TIMED_OUT && !isMain)         {              break;          }      } while (result != -ECONNREFUSED && result != -EBADF);      LOG_THREADPOOL("**** THREAD %p (PID %d)         IS LEAVING THE THREAD POOL err=%p\n",          (void*)pthread_self(), getpid(), (void*)result);      mOut.writeInt32(BC_EXIT_LOOPER);      talkWithDriver(false);  }

    ProcessState中有2个Parcel成员(mIn和mOut),由以上代码可见,Pool Thread会不断查询BD中是否有数据可读,若有,则保存在mIn;不停检查mOut是否有数据需要向BD发送,若有,则写入BD。

    根据第三节提到的:BpBinder通过调用transact向BD发送调用请求的数据,也就是说ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就讲述完毕。

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

  • 两个接口类

    1.BpINTERFACE

    client在获得server端service时,server端向client提供一个接口,client在这个接口基础上创建一个BpINTERFACE,使用此对象,client端的应用能够像本地调用一样直接调用server端的方法,而不必关系binder IPC实现。

     BpINTERFACE原型如下: /frameworks/native/include/binder/IInterface.h  template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase { public:                                 BpInterface(const sp<IBinder>& remote); protected:     virtual IBinder*            onAsBinder(); };

    可见,BpINTERFACE继承自INTERFACE、BpRefBase。

    BpINTERFACE既实现了service中各方法的本地操作,将每个方法的参数以Parcel的形式发送给BD。同时又将BpBinder作为了自己的成员来管理,将BpBinder存储在mRemote中,BpServiceManager通过调用BpRefBase的remote()来获得BpBinder指针。

    2.BnINTERFACE

    同样位于/frameworks/native/include/binder/IInterface.h     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();    }; 

由代码可知,BnInterface继承自INTERFACE、BBinder。

class BBinder : public

IBinder,由此可见,server端的binder操作及状态维护是通过BBinder来实现的。BBinder即为binder的本质。

3.接口类总结

由上节的描述及刚才对于两个接口类源代码分析可知:BpBinder是client端用于创建消息发送的机制,而BBinder是server端用于接口消息的通道。

BpBinder是client创建的用于消息发送的代理,其transact函数用于向IPCThreadState发送消息,通知其有消息要发送给BD,部分源代码如下:

/frameworks/native/libs/binder/BpBinder.cppstatus_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;        }        default:            return UNKNOWN_TRANSACTION;    }}

由BBinder的源码可知,其作用是当IPCThreadState收到BD消息时,通过transact方法将其传递给它的子类BnSERVICE的onTransact函数执行server端的操作。部分源码如下:

    /frameworks/native/libs/binder/Binder.cpp    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;    }

由上述可知,BpINTERFACE,BnINTERFACE均来自同一接口类IINTERFACE,由此保证了service方法在C/S两端的一致性。

  • writeStrongBinder和readStrongBinder
  1. writeStrongBinder是client将一个binder传送给server时需要调用的函数。

     具体源码如下: status_t Parcel::writeStrongBinder(const     sp<IBinder>& val) {     return flatten_binder(ProcessState::self(), val, this); } flatten_binder为: status_t flatten_binder(const sp<ProcessState>& proc, const sp<IBinder>& binder, Parcel* out) {     flat_binder_object obj;     obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;     if (binder != NULL) {         IBinder *local = binder->localBinder();         if (!local) {             BpBinder *proxy = binder->remoteBinder();         if (proxy == NULL) {             LOGE("null proxy");     }     const int32_t handle = proxy ? proxy->handle() : 0;     obj.type = BINDER_TYPE_HANDLE;     obj.handle = handle;     obj.cookie = NULL; } else {     obj.type = BINDER_TYPE_BINDER;     obj.binder = local->getWeakRefs();     obj.cookie = local; } } else {     obj.type = BINDER_TYPE_BINDER;     obj.binder = NULL;     obj.cookie = NULL; }  return finish_flatten_binder(binder, obj, out); }

    下边举例说明,addService源码为:

     /frameworks/native/libs/binder/IServiceManager.cpp 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的binder类型为BINDER_TYPE_BINDER,然而SM收到的Service的binder类型必须为BINDER_TYPE_HANDLE才会将其添加到svclist中,因此说,addService开始传递的binder类型为BINDER_TYPE_BINDER然而SM收到的binder类型为BINDER_TYPE_HANDLE,中间经历了一个改变,代码如下:

         drivers/staging/android/Binder.c static void binder_transaction(struct binder_proc *proc,            struct binder_thread *thread,            struct binder_transaction_data *tr, int reply){     ……     if (fp->type == BINDER_TYPE_BINDER)    fp->type = BINDER_TYPE_HANDLE;  else       fp->type = BINDER_TYPE_WEAK_HANDLE; fp->handle = ref->desc; …… }

    由以上函数可知,SM只保存了Service binder的handle和name,当client需要和Service通信时,如何才能获得Service得binder呢?需要由readStrongBinder来完成。

  2. readStrongBinder

    Client向server请求时,server向BD发送一个binder返回给SM(保存handle和name),当IPCThreadState收到由返回的parcel时,client通过这一函数将这个server返回给SM的binder读出。

     源码为: /frameworks/native/libs/binder/Parcel.cpp sp<IBinder> Parcel::readStrongBinder() const {     sp<IBinder> val;     unflatten_binder(ProcessState::self(), *this,      &val);     return val; } unflatten_binder为: status_t unflatten_binder(const sp<ProcessState>& proc,     const Parcel& in, sp<IBinder>* out) {     const flat_binder_object* flat = in.readObject(false);     if (flat) {         switch (flat->type) {             case BINDER_TYPE_BINDER:                 *out = static_cast<IBinder*>(flat->cookie);                 return finish_unflatten_binder(NULL, *flat, in);             case BINDER_TYPE_HANDLE:                 *out = proc->getStrongProxyForHandle(flat->handle);                 return finish_unflatten_binder(                     static_cast<BpBinder*>(out->get()),         *flat, in);         }     }     return BAD_TYPE; }

    由如上源码可知:发现如果server返回的binder类型为BINDER_TYPE_BINDER的话,直接获取这个binder;如果server返回的binder类型为BINDER_TYPE_HANDLE时,那么需要重新创建一个BpBinder返回给client。Client通过获得SMhandle来重新构建代理binder与server进行通信。

至此,native通信机制已构建完毕。

二、Java层的binder机制

下边来解析一下java层对于binder的封装过程,分四部分来进行介绍:Java层ServiceManager的结构、如何注册一个Service、如何得到一个Service、Service代理对象方法的过程。

*ServiceManager的结构:

  在Java层,ServiceManager的函数源码为:    /frameworks/base/core/java/android/os/ServiceManager.java    public final class ServiceManager {            }         public static IBinder getService(String name) {        }        public static void addService(String name, IBinder service) {        }        public static void addService(String name, IBinder service, boolean allowIsolated) {        }        public static IBinder checkService(String name) {        }        public static String[] listServices() throws RemoteException {        }        public static void initServiceCache(Map<String, IBinder> cache) {        }

由源码可知,ServiceManager没有继承其他类,下边我们来分析ServiceManager管理binder通信的流程。

  • 在Java层注册Service:

    通过ServiceManager的addService()可注册自己,其传输了两个参数:String name, IBinder service,分别为name和BBinder的子类对象,跟native层ServiceManager中Service的注册方法相一致。

      具体源码如下:  public static void addService(String name, IBinder service) {          try {              getIServiceManager().addService(name, service, false);          } catch (RemoteException e) {              Log.e(TAG, "error in addService", e);          }      }

    getIServiceManager().addService表明将此操作请求转发给了getIServiceManager(),返回一个IServiceManger类型的sServiceManager对象,源码如下:

      private static IServiceManager getIServiceManager() {          if (sServiceManager != null) {              return sServiceManager;          }          sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());          return sServiceManager;      }

    BinderInternal.getContextObject在native层得到BpBinder对象。

    ServiceManagerNative.asInterface 将BpBinder封装为Java层可用的ServiceManagerProxy对象。

    下面来通过源码具体分析BpBinder封装为ServiceManagerProxy的过程:

    static public IServiceManager asInterface(IBinder obj)

          {          if (obj == null) {              return null;          }          IServiceManager in =              (IServiceManager)obj.queryLocalInterface(descriptor);          if (in != null) {              return in;          }          return new ServiceManagerProxy(obj);      }

    由源码可知,通过asInterface的转换,BpBinder对象生成了ServiceManagerProxy对象。也就是说getIServiceManager()得到的是一个ServiceManagerProxy对象,那么ServiceManagerProxy又是什么,下边来具体分析一下。

      class ServiceManagerProxy implements IServiceManager {      public ServiceManagerProxy(IBinder remote) {          mRemote = remote;      }      public IBinder asBinder() {          return mRemote;      }      public IBinder getService(String name) throws RemoteException {      }      public IBinder checkService(String name) throws RemoteException {      }      public void addService(String name, IBinder service, boolean allowIsolated)              throws RemoteException {      }      public String[] listServices() throws RemoteException {      }      public void setPermissionController(IPermissionController controller)              throws RemoteException {      }      private IBinder mRemote;  }

    由源码可知,ServiceManagerProxy继承自IServiceManager,提供add、get、list、check等方法。由以上分析可知,通过getIServiceManager的便可得到ServiceManagerProxy对象,调用其addService方法便可进行注册,addService源码如下:

      public void addService(String name, IBinder     service, boolean allowIsolated)              throws RemoteException {          Parcel data = Parcel.obtain();          Parcel reply = Parcel.obtain();          data.writeInterfaceToken(IServiceManager.descriptor);      data.writeString(name);          data.writeStrongBinder(service);          data.writeInt(allowIsolated ? 1 : 0);          mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);          reply.recycle();          data.recycle();      }

    可知,将name和Service对象封装到Parcel中,调用transact()方法送出,并将当前操作标记为ADD_SERVICE_TRANSACTION,根据上一章提到的内容,transact()便会调用到BpBinder中,此时便进入到native层的使用,这部分内容已经在上一章节分析完毕,具体流程图如下: 

  • 客户端得到一个Service:

    主要流程如下:通过Java层的ServerManager得到相应的Service,然后通过asInterface()将得到的对象转为客户端可直接调用的代理对象,然后调用代理对象的updateAdnRecordsEfBySearch()方法。

      具体分析如下:  首先,通过ServerManager得到相应的BpBinder对象。  源码位于ServerManager.java中  public static IBinder getService(String name) {          try {              IBinder service = sCache.get(name);              if (service != null) {                  return service;              } else {                  return getIServiceManager().getService(name);              }          } catch (RemoteException e) {              Log.e(TAG, "error in getService", e);          }          return null;      }  可见,调用getIServiceManager()对象的getService()方法,代码如下。  private static IServiceManager getIServiceManager() {          if (sServiceManager != null) {              return sServiceManager;          }          // Find the service manager          sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());          return sServiceManager;      }

可知通过IServiceManager得到的是一个ServiceManager在Java层的代理对象,下边来分析此代理对象的getService( )方法。

    /frameworks/base/core/java/android/os/ServiceManagerNative.java    public IBinder getService(String name) throws RemoteException {            Parcel data = Parcel.obtain();            Parcel reply = Parcel.obtain();            data.writeInterfaceToken(IServiceManager.descriptor);            data.writeString(name);            mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);            IBinder binder = reply.readStrongBinder();            reply.recycle();            data.recycle();            return binder;        }

可见,getService请求被转交给native层,由上一章分析可知,native层得到请求后会将目标Service的BpBinder返回给客户端,得到BpBinder对象后,通过asInterface()得到一个Proxy对象,客户端便通过这个代理类调用服务端定义的各种方法。具体客户端得到Service的流程图如下: 

三、总结

Binder通信整体流程图如下:


原文地址:https://mobile100.gitbooks.io/android/content/paper/android_binderji_523628_1501210451_zhang_zhi_5eb72.html

0 0
原创粉丝点击