在阅读Replugin源码时, RePlugin初始化涉及到进程间通信的问题, 常驻进程通过PmHostSvc统筹插件的使用, 其他进程获取常驻进程的代理对象, 然后对插件进行操作.阅读Replugin时对这一块进程间通信的流程并没有深入进行分析, 这里单独拿出来进行分析
进程间通信
多进程通信不管是Android的binder还是linux的channel最终都是通过共享内存的读写来实现的, 两个或多个进程都能读取内存中的某一个文件, 一个进程负责写, 一个进程负责读, 这样就实现了进程间通信.
Android使用AIDL的方式实现IPC
IPC通信过程
1、首先客户端要连接服务端
2、然后服务端会返回一个客户端的对象(代理对象) 3、然后客户端使用这个代理对象其中的方法时, 系统会先调用服务端的方法, 然后将运算的结果返回给客户端(其实并不是用了这个对象的方法, 而是去服务端里运算, 然后再返回给客户端)
1.创建AIDL文件
interface AidlBean {
void setData(int data);
int getData();
}
2.build自动生成AidlBean.java文件
public interface AidlBean extends android.os.IInterface {
public void setData(int data) throws android.os.RemoteException;
public int getData() throws android.os.RemoteException;
}
AidlBean的结构:
1、创建的类AidlBean继承IInterface接口
2、内部类Stub继承Binder 3、asInterface方法, 判断如果不是同一个进程会返回代理类 4、每个方法对应一个id, 用于在跨进程访问时确定访问的是哪个方法, 通过transact方法再调用服务端的onTransact方法
3.Stub.asInterface
public static com.hb.test.AidlBean asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.hb.test.AidlBean))) {
return ((com.hb.test.AidlBean)iin);
}
return new com.hb.test.AidlBean.Stub.Proxy(obj);
}
}
4.Client端transact方法
@Override
public void setData(int data) 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(data);
boolean _status = mRemote.transact(Stub.TRANSACTION_setData, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setData(data);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
1、创建输出类型data
2、创建接收类型reply 3、创建需要的参数 4、将参数写入data中 5、发起远程调用, 当前线程挂起调用mRemote.transact()方法, 这个方法的实现在Binder中, 他会调用服务端的onTransact方法, 直到有返回结果 6、从_result中取出返回结果
5.Server端onTransact方法
@Override
public boolean onTransact(int code, android.os.Parcel data, Parcel reply, int flags) {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
this.setData(_arg0);
reply.writeNoException();
return true;
}
服务端接到请求会走到onTransact方法, 这个方法运行在服务端的Binder线程池中
1、通过id确定访问哪个方法
2、从目标参数data取出需要的参数 3、调用请求的相应方法 4、将返回值写入reply 5、返回true成功, false客户端访问失败, 实际当中可根据这个特性来做远程校验