您的位置:华清远见教育科技集团 >> 新闻动态 >> Android资料 >> Android IBinder通信机制  
 
Android IBinder通信机制
分享到:

在Linux中,进程间通信机制主要有D-BUS和OpenBinder两种,在Android中,通过IBinder对OpenBinder进行了封装,IBinder通信机制是一个轻量级的远程过程调用机制,用于进程内和进程间的高性能的通信。IBinder传递的数据被封装在android.os.Parcel中。需要注意的是,android.os.Parcel并非一种通用的序列化机制,而是专为IBinder设计的。D-BUS通信机制由于Blue-Z协议栈的需求在Android局部进行了使用。

在Android中,远程过程调用被封住到IBinder类中。在底层的实现上和处理器间的远程过程调用类似,如图1-1所示为IBinder通信的类图。


图1-1 IBinder通信

IBinder:: transact()是IBinder接口中一个比较重要的方法,其原型如下:

virtual status_t transact( uint32_t code, //请求的ID号
                     const Parcel& data, //请求的参数
                     Parcel* reply, //返回的结果
                     uint32_t flags=0)=0; //标识符

对开发者而言,Android目前只提供了FLAG_ONEWAY一种标识符,表示调用者在发出请求后,立即返回,不必等待被调用者返回结果。在Binder驱动中,目前提供了4种标识符:

TF_ONE_WAY //调用者立即范围,异步调用
    TF_ROOT_OBJECT //数据为组件的根对象
    TF_STATUS_CODE //数据为一个32bit的状态码
    TF_ACCEPT_FDS //允许以文件标识符的方式响应

如果IBinder指向的是一个客户端代理,那么IBinder:: transact()方法只是把请求发送给服务器。服务端的IBinder:: transact()方法则提供实际的服务。

在客户端,BpBinder类是远程IBinder对象在本地进程的一个代理,其transact()方法实现为:

status_t BpBinder::transact(
      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        //一旦一个binder被销毁,将无法再被激活
      if (mAlive) {
        status_t status=IPCThreadState::self()->transact(
          mHandle, code, data, reply, flags);
        if (status==DEAD_OBJECT) mAlive=0;
        return status;
      }
      return DEAD_OBJECT;
    }

其中IPCThreadState:: transact()会把请求经内核模块发送给服务器端,服务器端处理完请求之后,沿原路将处理结果返给调用进程。这里的请求是同步操作,它会等待直到结果返回为止。

在BpBinder之上进行简单封装,我们可以得到与服务对象相同的接口,调用者无须关心调用的对象是远程的还是本地的。此类实现在Android的多个场景获得了应用。与BpBinder类似的接口为BpRefBase,而BBinder则是一个本地对象。

在各种原生服务的实现上,通常会继承BpRefBase的BpInterface接口来实现远程代理,继承Bbinder的BnInterface接口来实现本地对象。

为了使C代码也能调用Java实现的服务,android_os_Binder_init里的JavaBBinder对Java 里的Binder对象进行包装。下面是JavaBBinder:: onTransact()方法的实现:

virtual status_t onTransact(
      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags=0)
    {
      JNIEnv* env=javavm_to_jnienv(mVM); //转换Java
      LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
      jboolean res=env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
        code, (int32_t)&data, (int32_t)reply, flags);
      jthrowable excep=env->ExceptionOccurred();
      if (excep) {
        report_exception(env, excep,
          "*** Uncaught remote exception! "
          "(Exceptions are not yet supported across processes.)");
        res=JNI_FALSE;
          //清除JNI的本地记数因子
        env->DeleteLocalRef(excep);
      }
      return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }

JavaBBinder的实现位于android_util_Binder.cpp文件中。

IBinder不提供广播消息,但通过ActivityManagerService服务可以实现广播,触发广播需要调用 ActivityManagerProxy::broadcastIntent()方法,接收广播消息需要首先实现接口BroadcastReceiver,然后调用 ActivityManagerProxy::registerReceiver()方法进行注册。

 更多相关文章

·Android ONC RPC远程调用
·Dalvik虚拟机原生方法的注册
·Android Dalvik虚拟机启动
·Android服务管理器守护进程
·Android init.rc脚本语