Binder简要分析记录

简介

Binder 是一种进程间通信机制,实现进程间通讯。

比较

Linux内核提供的IPC机制:管道、Socket 、共享内存、消息队列等。

共享内存使多个进程可以访问同一个内存空间,管理混乱;
管道耗费性能,需要两次拷贝数据(copy_from_user从客户端拷贝数据到内核空间、copy_to_user从内核空间拷贝数据到服务端);
Socket适合用于网络通讯,传输效率低,开销大,但是不适用于进程间通讯。(2次数据拷贝)

Binder通过驱动在内核空间拷贝数据,不需要额外的同步处理。只要进行一次数据拷贝,性能仅次于共享内存。

进程的 UID 是鉴别进程身份的重要标志。Binder支持通讯双方身份校验(UID/PID),安全性较高。
注:传统的进程通讯方式没有对通讯双方的身份做严格的验证,如Socket通讯。

Binder既支持实名Binder也支持匿名Binder。

角色

Binder基于C/S架构。实现面向对象的调用方式,在使用Binder时,就和调用一个本地对象实例一样。
Server(用户空间):服务端
Client(用户空间):客户端
ServiceManager(用户空间):Server和Client之间的桥梁。Client可以通过ServiceManager获得Server中Binder实体的引用。Server将自己的Binder引用注册到ServiceManager中,Client通过特定的key从ServiceManager中获取Server的Binder引用。
Binder驱动(内核空间):一种虚拟设备驱动。连接Server、Client和ServiceManager的桥梁,实现进程之间 Binder 通信(内存映射、调用mmap()函数))。

对象

IBinder :实现跨进程传输的能力;
IInterface:Server端提供的功能;
Binder:java层Binder类;
Binder本地对象、BinderProxy本地代理(Binder内部类)。Binder和BinderProxy都继承自IBinder,Binder驱动自动完成Binder与BinderProxy的转换。
Stub(抽象类):继承Binder,实现IInterface接口

public interface ILoginInterface extends android.os.IInterface
{
  /** Default implementation for ILoginInterface. */
  public static class Default implements com.sc.binder.test.ILoginInterface
  {
    @Override public void login() throws android.os.RemoteException
    {
    }
    @Override public void loginCallback(boolean res, java.lang.String user) throws android.os.RemoteException
    {
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder implements com.sc.binder.test.ILoginInterface
  {
    private static final java.lang.String DESCRIPTOR = "com.sc.binder.test.ILoginInterface";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.sc.binder.test.ILoginInterface interface,
     * generating a proxy if needed.
     */
    public static com.sc.binder.test.ILoginInterface asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.sc.binder.test.ILoginInterface))) {
        return ((com.sc.binder.test.ILoginInterface)iin);
      }
      return new com.sc.binder.test.ILoginInterface.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
    {
      java.lang.String descriptor = DESCRIPTOR;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_login:
        {
          data.enforceInterface(descriptor);
          this.login();
          reply.writeNoException();
          return true;
        }
        case TRANSACTION_loginCallback:
        {
          data.enforceInterface(descriptor);
          boolean _arg0;
          _arg0 = (0!=data.readInt());
          java.lang.String _arg1;
          _arg1 = data.readString();
          this.loginCallback(_arg0, _arg1);
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.sc.binder.test.ILoginInterface
    {
      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 login() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().login();
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      @Override public void loginCallback(boolean res, java.lang.String user) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeInt(((res)?(1):(0)));
          _data.writeString(user);
          boolean _status = mRemote.transact(Stub.TRANSACTION_loginCallback, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().loginCallback(res, user);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.sc.binder.test.ILoginInterface sDefaultImpl;
    }
    static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_loginCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    public static boolean setDefaultImpl(com.sc.binder.test.ILoginInterface impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.sc.binder.test.ILoginInterface getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  public void login() throws android.os.RemoteException;
  public void loginCallback(boolean res, java.lang.String user) throws android.os.RemoteException;
}

aidl

interface ILoginInterface {

   void login();

   void loginCallback(boolean res,String user);
}

Server

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        return new ILoginInterface.Stub() {
            @Override
            public void login() throws RemoteException {
                Log.d("binder >>> ", "serviceStartActivity");
                serviceStartActivity();
            }

            @Override
            public void loginCallback(boolean res, String user) throws RemoteException {

            }
        };
    }

    private void serviceStartActivity() {
        Intent intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
}

Client

private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iLogin = ILoginInterface.Stub.asInterface(service);
            Log.d("binder >>> ", "onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    
 public void startLogin(View view) {
        if (iLogin != null) {
            try {
                iLogin.login();
            } catch (RemoteException e) {
            }
        } 
    }

通讯过程

1、Client获取Server的代理接口BinderProxy(代理定义的方法与Server一一对应)
2、Client发送数据(copy_from_user)到BinderProxy(内核缓存区);
2、BinderProxy将数据打包成Parcel对象 ;
3、BinderProxy调用remote.transact(),将打包的Parcel对象发送给内核中的Binder驱动
4、Binder驱动找到真正的Binder对象,唤醒Server进程;
5、Server进程读取Binder请求数据,调用onTransact()(检验、解包),执行目标方法;(内核缓存区与Binder创建的接收缓存区存在映射关系,Server与Binder创建的接收缓存区存在映射关系)。
6、Server返回结果给Binder驱动;
7、Binder驱动返回结果给Client。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值