Android Binder机制浅析

Binder机制听的比较多,在实际的应用中主要是AIDL跨进程通信的实现原理,但是我们平时也很少深入的了解;但是在阅读系统源码的时候尤其是四大组件的启动流程,都和Binder息息相关,APP进程通过Binder和SystemServer进程通信调用ActivityManagerService的方法,经过层层调用之后,SystemServer进程ActivityManagerService的方法又通过Binder和APP进程通信,调用ApplicationThread(ActivityThread的内部类)的方法;因为Binder机制内容实在比较多,涉及到 内核空间(Kernel)、Native层,Java层;在阅读了众多大神的文章之后,加深理解,只记录下对Binder机制的浅显理解;

Android跨进程通信:图文详解 Binder机制 原理

Binder系列—开篇
Binder系列1—Binder Driver初探
Binder系列2—Binder Driver再探
Binder系列3—启动Service Manager
Binder系列4—获取Service Manager
Binder系列5—注册服务(addService)
Binder系列6—获取服务(getService)
Binder系列7—framework层分析
Binder系列8—如何使用Binder
Binder系列9—如何使用AIDL
Binder系列10—总结

1、准备知识
1.1、进程空间的划分
  • 一个进程空间分为 用户空间 & 内核空间(Kernel),即把进程内 用户 & 内核 隔离开来
  • 二者区别:
    1. 进程间,用户空间的数据不可共享;
    2. 进程间,内核空间的数据可共享;

所有进程共用1个内核空间

  • 进程内 用户空间 & 内核空间 进行交互 需通过 系统调用,主要通过函数:
  1. copy_from_user():将用户空间的数据拷贝到内核空间;
  2. copy_to_user():将内核空间的数据拷贝到用户空间;
1.2、进程隔离和跨进程通信(IPC)
  • 进程隔离
    为了保证 安全性 & 独立性,一个进程 不能直接操作或者访问另一个进程,即Android的进程是相互独立、隔离的
  • 跨进程通信( IPC
    即进程间需进行数据交互、通信
  • 跨进程通信的基本原理
    在这里插入图片描述

a. 而Binder的作用则是:连接 两个进程,实现了mmap()系统调用,主要负责 创建数据接收的缓存空间 & 管理数据接收缓存
b. 注:传统的跨进程通信需拷贝数据2次,但Binder机制只需1次,主要是使用到了内存映射,具体下面会详细说明

1.3、内存映射

操作系统:图文详解 内存映射

2、Binder跨进程通信机制模型
2.1、模型原理图

Binder 跨进程通信机制 模型 基于 Client - Server 模式
在这里插入图片描述

2.2、模型组成角色说明

在这里插入图片描述

主要讲解Binder驱动的作用和原理:

  • 简介
    在这里插入图片描述

  • Binder跨进程通信的核心原理
    在这里插入图片描述

2.3、模型原理步骤说明

在这里插入图片描述

3.4、额外说明

说明1:Client进程、Server进程 & Service Manager 进程之间的交互 都必须通过Binder驱动(使用 open 和 ioctl文件操作函数),而非直接交互
原因:

  1. Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互;
  2. Binder驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互;

所以,原理图可表示为以下:

虚线表示并非直接交互
在这里插入图片描述

说明2: Binder驱动 & Service Manager进程 属于 Android基础架构(即系统已经实现好了);而Client 进程 和 Server 进程 属于Android应用层(需要开发者自己实现)。

所以,在进行跨进程通信时,开发者只需自定义Client & Server 进程 并 显式使用上述3个步骤,最终借助 Android的基本架构功能就可完成进程间通信
在这里插入图片描述

3 Binder机制在Android中的应用
3.1 AIDL

AIDL类图
在这里插入图片描述

创建IMyAidlInterface.aidl文件

interface IMyAidlInterface {
    int add(int a,int b);
}

Build之后生成的IMyAidlInterface.java文件;其中包含两个内部类Stub(存根)和Proxy(代理类);

Stub(存根):通过继承Stub类,重写IMyAidlInterface接口中方法的具体实现;Service端持有Stub子类的实例,通过onBind()方法返回;经过Binder跨进程通信,最终会将Stub子类的实例,通过ServiceConnection的onServiceConnected()方法参数方式,传递到Client端;

Proxy(代理类):实现IMyAidlInterface接口类;

//IMyAidlInterface继承IInterface接口;
public interface IMyAidlInterface extends android.os.IInterface {
   
    //Stub(存根)是Binder的子类,又实现了IMyAidlInterface接口;
    //通过继承Stub类,重写IMyAidlInterface接口中方法的具体实现;Service端持有Stub子类的实例,
    //通过onBind()方法返回;经过Binder跨进程通信,最终会将Stub子类的实例,
    //通过ServiceConnection的onServiceConnected()方法参数方式,传递到Client端;
    public static abstract class Stub extends android.os.Binder implements com.mydesign.modes.IMyAidlInterface {
        private static final java.lang.String DESCRIPTOR = "com.mydesign.modes.IMyAidlInterface";
       
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
       
         //将IBinder对象转换为对应的接口;如果通过queryLocalInterface()方法获取的IInterface对象为null,
        //则通过Proxy(代理类)创建;Client端ServiceConnection的onServiceConnected()方法调用,
        public static com.mydesign.modes.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.mydesign.modes.IMyAidlInterface))) {
                return ((com.mydesign.modes.IMyAidlInterface) iin);
            }
            return new com.mydesign.modes.IMyAidlInterface.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 {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
        
		//Proxy(代理类)实现了IMyAidlInterface接口;
        private static class Proxy implements com.mydesign.modes.IMyAidlInterface {
            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 int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public int add(int a, int b) throws android.os.RemoteException;
}

IRemoteService类继承IMyAidlInterface.Stub;同时Stub是,Service端持有Stub子类的实例,通过onBind()方法返回;经过Binder跨进程通信,最终会将Stub子类的实例,通过ServiceConnection的onServiceConnected()方法参数方式,传递到Client端;

public class IRemoteService extends IMyAidlInterface.Stub {
    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}

RemoteService作为Service端,client调用bindService()方法之后,Binder跨进程通信,最后调用onCreate()(第一次),进而调用onBind()方法将iRemoteService返回,通过跨进程通信,通过ServiceConnection的onServiceConnected()方法参数方式,传递到Client端;

public class RemoteService extends Service {
    private IRemoteService iRemoteService = new IRemoteService();
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return iRemoteService;
    }
}

AIDLTestActivity作为client端;bindService()方法之后,ServiceConnection的onServiceConnected()方法被调用,得到IMyAidlInterface对象iMyAidlInterface后再调用其方法;有兴趣的可以了解下BindService的流程;

public class AIDLTestActivity extends Activity implements View.OnClickListener {
    private Intent intent;
    private IMyAidlInterface iMyAidlInterface;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }
        
        @Override
        public void onServiceDisconnected(ComponentName name) {}
    };
    private void toBindService() {
        intent = new Intent(this, RemoteService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }
    
     private void addTest() {
        try {
            int add = iMyAidlInterface.add(20, 30);
            Log.e(TAG, "add:::" + add);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

Client调用IMyAidlInterface的add()方法的流程
在这里插入图片描述
主要调用是在步骤2和3中;

Proxy的add()方法主要1)从对象池中获取对象,用于存储参数的Parcel对象data和用于存储返回值的Parcel对象reply;2)调用Stub的transact()方法,读取data中写入的参数,运算之后,写入返回值写入reply;3)读取reply中存储的值,并返回给Client;

public int add(int a, int b) throws android.os.RemoteException {
    //从对象池中回去一个Parcel对象,参数对象;
    android.os.Parcel _data = android.os.Parcel.obtain();
    //返回值对象;
    android.os.Parcel _reply = android.os.Parcel.obtain();
    int _result;
    try {
        //写入,存储;
        _data.writeInterfaceToken(DESCRIPTOR);
        _data.writeInt(a);
        _data.writeInt(b);
        //调用Stub类的transact()方法;
        mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
        _reply.readException();
        //读取存储的值;
        _result = _reply.readInt();
    } finally {
        _reply.recycle();
        _data.recycle();
    }
    return _result;
}

Stub的onTransact():读取data中写入的参数,运算之后,写入返回值写入reply;

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
    switch (code) {
        case INTERFACE_TRANSACTION: {
            reply.writeString(DESCRIPTOR);
            return true;
        }
        case TRANSACTION_add: {
            data.enforceInterface(DESCRIPTOR);
            int _arg0;
            _arg0 = data.readInt();
            int _arg1;
            _arg1 = data.readInt();
            int _result = this.add(_arg0, _arg1);
            reply.writeNoException();
            reply.writeInt(_result);
            return true;
        }
    }
    return super.onTransact(code, data, reply, flags);
}

内核空间(Kernel),Native层 由于个人能力问题就不去了解;以上是个人粗浅的理解,如有问题,请多指导,谢谢!

参考文档

Android跨进程通信:图文详解 Binder机制 原理

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值