Android进阶(六)Binder机制

1、进程通讯

一、进程隔离:

进程隔离是为保护操做系统中进程互不干扰而设计的一组不一样硬件和软件的技术。进程数据不共享,进程A的虚拟地址和进程B的虚拟地址不一样,这样就防止进程A将数据信息写入进程B,保证了数据的安全性。 java

  • 进程空间分为内核空间和用户空间,内核空间(Kernel)是系统内核运行的空间。用户空间(User Space)是用户程序运行的空间,他们之间是隔离的。
  • 内核有访问的全部权限,用户空间也能够经过系统接口去访问内核空间。用户空间能够经过内核空间(相似于中介者)进行相互访问。

二、Linux进程间IPC方式:

  • 管道
  • 消息队列
  • 共享内存
  • 套接字
  • 信号量
  • 信号

Linux 下的传统 IPC 通讯原理: android

传输过程:
内存缓存区 --> 内核缓存区 --> 内存缓存区,须要 2 次数据拷贝;

三、Binder机制的特色

(1)传输性能

  • Binder数据拷贝只须要一次,而消息队列、管道、Socket等须要两次,共享内存一次拷贝都不须要。Binder性能仅次于共享内存。

(2)稳定性缓存

  • Binder基于C/S架构,Server端和Client端相对独立,稳定性好。
  • 共享内存没有Server端和Client端的区分,可能存在同步死锁等问题。Binder稳定性优于共享内存。

(3)安全性安全

  • 传统的Linux通讯方式没法获取对方进程的UID,因此访问接入点是开放的,不安全。
  • Android为每一个应用程序分配了本身的UID,做为自身的标识。Binder的方式能够经过UID创建私有通道,Binder的安全性更高。

2、Binder机制实现原理

一、内存映射

Binder IPC正是基于内存映射(mmap)来实现的 bash

Binder通讯过程:

  • 首先 Binder 驱动在内核空间建立一个数据接收缓存区;
  • 接着在内核空间开辟一块内核缓存区,创建内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
  • 发送方进程经过系统调用 copy_from_user() 将数据 copy 到内核中的内核缓存区,因为内核缓存区和接收进程的用户空间存在内存映射,所以也就至关于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通讯。

二、Binder通讯模型

  • 包括 Client、Server、ServiceManager、Binder 驱动。
  • 其中 Client、Server、Service Manager 运行在用户空间,Binder 驱动运行在内核空间。
  • 对于Client,Binder是Server本地对象的一个引用,这个引用其实是一个代理对象,Client经过这个代理对象来间接访问Server的本地对象。
  • 对于Server,Binder是提供具体实现的本地对象,需向ServiceManager注册。
  • Binder驱动是链接Client来Server的桥梁,负责将代理对象转化为本地对象,并将Server的执行结果返回给Client。
  • ServiceManager它保存了Server Binder字符名称和Binder引用的映射,Client经过它来找到Server的Binder引用。

三、Binder通讯过程:

  • 一个进程使用 BINDERSETCONTEXT_MGR 命令经过 Binder 驱动将本身注册成为 ServiceManager;
  • Server 经过驱动向 ServiceManager 中注册 Binder,代表能够对外提供服务。驱动为这个 Binder 建立位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager,ServiceManger 将其填入查找表。
  • Client 经过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用,经过这个引用就能实现和 Server 进程的通讯。

3、AIDL

一、AIDL使用的基本步骤

(1)生成AIDL接口(new->AIDL->AIDL File)架构

interface MyWindowManager {
    void sysout();
}
复制代码

生成AIDL文件以后,比起之前多了一个叫作 aidl 的包,并且他的层级是和 java 包相同的。
(2)编译MyWindowManager.aidl生成Java文件ide

public interface MyWindowManager extends android.os.IInterface {
  /** Local-side IPC implementation stub class. */
  //Stub 继承 Binder, 说明它是一个 Binder 本地对象;实现 IInterface 接口,代表Server能够提供的方法
  public static abstract class Stub extends android.os.Binder
      implements com.example.myview.binder.MyWindowManager {
    private static final java.lang.String DESCRIPTOR = "com.example.myview.binder.MyWindowManager";

    /** Construct the stub at attach it to the interface. */
    public Stub() {
      this.attachInterface(this, DESCRIPTOR);
    }

    public static com.example.myview.binder.MyWindowManager asInterface(android.os.IBinder obj) {
      if ((obj == null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin != null) && (iin instanceof com.example.myview.binder.MyWindowManager))) {
        return ((com.example.myview.binder.MyWindowManager) iin);
      }
      return new com.example.myview.binder.MyWindowManager.Stub.Proxy(obj);
    }

    @Override
    public android.os.IBinder asBinder() {
      return this;
    }

    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
        throws android.os.RemoteException {
      ......
      return super.onTransact(code, data, reply, flags);
    }

    //Binder本地代理对象
    private static class Proxy implements com.example.myview.binder.MyWindowManager {
      private android.os.IBinder mRemote;

      Proxy(android.os.IBinder remote) {
        mRemote = remote;
      }

      @Override
      public android.os.IBinder asBinder() {
        return mRemote;
      }

      public java.lang.String getInterfaceDescriptor() {
        return DESCRIPTOR;
      }

      @Override
      public void sysout() throws android.os.RemoteException {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          mRemote.transact(Stub.TRANSACTION_sysout, _data, _reply, 0);
          _reply.readException();
        } finally {
          _reply.recycle();
          _data.recycle();
        }
      }
    }

    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_sysout = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  }

  public void sysout() throws android.os.RemoteException;
}
复制代码
  • MyWindowManager继承了IInterface,是Client和Server通讯的接口
  • Stub为静态抽象内部类,继承了Binder。其子类须要实现MyWindowManager接口,是Server的Binder的本地对象
  • Stub.Proxy为静态内部类,内部包含了IBinder对象,是Server在Client中的本地代理对象,将参数序列化后交给mRemote处理,实现了跟远程Stub的通讯
  • asInterface方法一般是Client在bindService成功后,由Client来调用的,做用是将绑定成功后返回的IBinder对象转换为具体的IInterface接口。Client拿到这个IInterface接口后跟Server进行通讯

(3)Server端提供方法的具体实现工具

public class MyWindowManagerService extends Service {
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
    return mWindowManager;
  }

  private final MyWindowManager.Stub mWindowManager = new MyWindowManager.Stub() {
    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble,
        String aString) throws RemoteException {

    }

    @Override
    public void sysout() throws RemoteException {
      Log.e("hj", "sysout: " );
    }
  };

}
复制代码

(4)其余进程的Activity实现跟Service的通讯性能

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = new Intent(this, MyWindowManagerService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
  }

  ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
      MyWindowManager windowManager = MyWindowManager.Stub.asInterface(service);
      try {
        windowManager.sysout();
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
  };
}
复制代码

二、IBinder/IInterface/Binder/BinderProxy/Stub

  • IBinder : IBinder 是一个接口,表明了一种跨进程通讯的能力。只要实现了这个借口,这个对象就能跨进程传输。
  • IInterface : IInterface 表明的就是 Server 进程对象提供了哪些方法
  • Binder : Java 层的 Binder 类,表明的其实就是 Binder 本地对象。Proxy 类是 Binder 类的一个内部类,它表明远程进程的 Binder 对象的本地代理;这两个类都继承自 IBinder, 于是都具备跨进程传输的能力;实际上,在跨越进程的时候,Binder 驱动会自动完成这两个对象的转换。
  • Stub : AIDL 的时候,编译工具会给咱们生成一个名为 Stub 的静态内部类;这个类继承了 Binder, 说明它是一个 Binder 本地对象,它实现了 IInterface 接口,代表它具备 Server 承诺给 Client 的能力;Stub 是一个抽象类,具体的 IInterface 的相关实现须要本身实现。

参考文章:
Android Binder设计与实现 - 设计篇
为何 Android 要采用 Binder 做为 IPC 机制?
写给 Android 应用工程师的 Binder 原理剖析ui

相关文章
相关标签/搜索