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 ManagerBinder系列4—获取Service ManagerBinder系列5—注册服务(addService)Binder系列6—获取服务(getService)Binder系列7—framework层分析Binder系列8—如何使用BinderBinder系列9—如何使用AIDLBinder系列10—总结
1、准备知识
1.1、进程空间的划分
- 一个进程空间分为 用户空间 & 内核空间(Kernel),即把进程内 用户 & 内核 隔离开来
- 二者区别:
- 进程间,用户空间的数据不可共享;
- 进程间,内核空间的数据可共享;
所有进程共用1个内核空间
- 进程内 用户空间 & 内核空间 进行交互 需通过 系统调用,主要通过函数:
- copy_from_user():将用户空间的数据拷贝到内核空间;
- 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文件操作函数),而非直接交互。
原因:
- Client进程、Server进程 & Service Manager进程属于进程空间的用户空间,不可进行进程间交互;
- 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层 由于个人能力问题就不去了解;以上是个人粗浅的理解,如有问题,请多指导,谢谢!