0. what is IPC

Inter-Process commonication 进程间通信,跨进程通信

ps:注意区分跨线程和跨进程

1. android 跨进程通信形式

  • intent-bundle
  • broadcast
  • content provider(*)
  • messagener(*)
  • AIDL(*)
  • file

画*的为比较难的,其中难度系数 AIDL>Messagener>ContentProvider,具体的使用方法请自行搜索,说一下AIDL的流程和各自的特性。

先说下特性吧 messagener 是串行处理的 AIDL支持并发处理,所以根据自己需要 AIDL 使用过程不再阐述,自行百度,下面说下跨进程发生了啥

调用过程看起来是在客户端直接调用binder然后强转调用方法即可,但是,但是,说下隐藏点。

  1. onserviceconnected

    • 参数 IBinder 有两种类型 Binder 和 BinderProxy(没见过吧) ,其中Binder 类型是非跨进程的时候拿到的,BinderProxy 是跨进程的,然后看各自的asInterface方法(这里asinterface 需要转成你定义的接口才能调用)

      onserviceConnected
      
      IBookManager manager = IBookManager.Stub.asInterface(service)
      //service 可能是Binder 类型或者是 BinderProxy,为什么是这两种类型自行百度,因为我也没看明白
      

      Binder

      /**
      * Use information supplied to attachInterface() to return the
      * associated IInterface if it matches the requested
      * descriptor.
      */
      public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor.equals(descriptor)) {
            //这个owner 在构造函数里调用attch 方法设置了,所以会返回自己
            return mOwner;
        }
        return null;
      }
      

      BinderProxy

      public IInterface queryLocalInterface(String descriptor) {
            return null;
      }
      

      调用方

      /**
      * Cast an IBinder object into an com.test.aidl.IBookManager interface,
      * generating a proxy if needed.
      */
      public static com.test.aidl.IBookManager asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
       //这里,看到了,如果是Binder那么能查询到就会直接返回,然后调用,如果返回null(binderproxy)那么创建一个代理类回去
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.test.aidl.IBookManager))) {
            return ((com.test.aidl.IBookManager) iin);
        }
        return new com.test.aidl.IBookManager.Stub.Proxy(obj);
      }
      

      看了上边的几段代码应该能明确了如果 是跨进程调用的话,会返回给客户端一个服务端Binder的代理对象,这个代理对象继承自stub(binder)的实现,所以具有同样的方法,至于调用参照2.

  2. binder 代理类的调用 客户端拿到binder (实际是个代理,客户端不知道也不care)之后,看是调用了,调用到代理的各种方法,举个栗子

     @Override
     public java.util.List<com.test.aidl.Book> getBookList() throws android.os.RemoteException {
         android.os.Parcel _data = android.os.Parcel.obtain();
         android.os.Parcel _reply = android.os.Parcel.obtain();
         java.util.List<com.test.aidl.Book> _result;
         try {
             _data.writeInterfaceToken(DESCRIPTOR);
             mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);
             _reply.readException();
             _result = _reply.createTypedArrayList(com.test.aidl.Book.CREATOR);
         } finally {
             _reply.recycle();
             _data.recycle();
         }
         return _result;
     }
    

    首先看到了一大堆序列化的东西,为啥需要序列化???想想intent是怎么传递数据的?为啥intent 那么传递?因为支持跨进程啊,可以看到,实际的调用是mRemote 对象,mRemote对象是啥? 上边的asInterface 里边的最后一句

    return new com.test.aidl.IBookManager.Stub.Proxy(obj);
    

    就是它了 ,所以mRemote 是obj 也就是一个BinderProxy 对象,敲黑板重点来了:

    1. 这个obj(BinderProxy 对象) 是remote 进程的binder 的代理
    2. 跨进程调用的实际是 transcat 方法
    3. Stub.TRANSACTION_getBookList 这是个id,标识了要真正调用的方法 所以过程为,客户端拿到了一个代理A,这个代理A包装了一个B 的代理B+,客户端调用 A->B+ ->驱动跨进程->B->真正的方法

      remote进程 的解析,并回写结果
      @Override
      public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
       switch (code) {
           case TRANSACTION_getBookList: {
               data.enforceInterface(DESCRIPTOR);
               java.util.List<com.test.aidl.Book> _result = this.getBookList();
               reply.writeNoException();
               reply.writeTypedList(_result);
               return true;
           }
       }
       return super.onTransact(code, data, reply, flags);
      }
      

      全是代理。大概是这样 client <——> Binder驱动 <——> remote,只是Binder 驱动那层我们感知不到,所以看起来是两个进程直接通信的。 另外还有messagener 通信,据说是调用优化版,没有细看代码。以上基本就是AIDL 的整个过程了,至于绑定服务相关和驱动层还没看估计短时间也不会看了。

名称 优点 缺点 适用场景
bundle 简单易用 只能传输bundle支持的数据类型 四大组件间的进程间通信
文件 简单易用 不适合高并发,无法即时通信 无并发需求,交换简单数据
AIDL 支持一对多并发,实时通信 使用复杂,需要处理线程同步 一对多通信,RPC需求
Messagener 功能一般,支持一对多串行实时通信 不能很好的处理高并发,不支持rpc(个人理解是因为单向通信,不支持返回),只能传递bundle支持的数据类型 低并发一对多计时通信无rpc,或者不需要的返回值的rpc请求
contentprovider 在数据源访问方向功能强大,支持一对多并发数据共享,可通过call扩展操作 受约束的AIDL,提供CRUD操作 一对度进程间的数据共享

大神链接 Binder学习指南-Weishu's Notes

results matching ""

    No results matching ""