一 多进程之间的通信
由于不同进程所拥有的地址是两块不同的地址空间,所以不能直接通过共享内存共享数据了。
Linux常用跨进程通信方式:管道,信号量,共享内存,socket
Android常用跨进程通信方式:Intent ,共享文件,SharedPreferences,Binder,socket,基于Binder的Messenger.下面详细学习进程间的通信方式。
二,进程之间的通信方式
1.Binder
Binder是安卓中最重要的IPC通信方式了,一个应用进程的创建,应用进程中组件的生命周期的调度,系统服务的使用...处处都是binder,从而也可以看出,安卓中进程间的通信是非常频繁的,一句话来说,在Binder通信机制的强有力支持下,安卓进程间进行了友好的数据交互。
Binder是进程间通信的一种架构,这个架构分为:
- 服务端接口(Bn端)
- 客户端接口(Bp端)
- Binder驱动
1.1 拆分xxx.aidl文件生成类
由aidl生成的java文件(一个接口文件;该接口文件中嵌套一个抽象的类Stub,该类实现外边的接口文件,没有实现具体接口方法,接口方法由其子类实现;抽象类中有一个proxy类,该类是抽象Stub的代理类,同时也实现了最外层的接口文件,proxy文件的作用是将客户端的输入包装成统一形式,具体的业务实现在服务端 Stub的子类中)由aidl文件系统帮我们生成的三个文件,如下:
a) 接口 IXXX extends IInterface
b) abstract class Stub extends Binder imp IXXX 该类重写了binder的 OnTransact方法:
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags){
.................
case TRANSACTION_startScan:
{
data.enforceInterface(DESCRIPTOR); //校验
java.lang.String[] _arg0;
_arg0 = data.createStringArray(); //读取参数
com.miui.guardprovider.aidl.IVirusObserver _arg1;
_arg1 = com.miui.guardprovider.aidl.IVirusObserver.Stub.asInterface(data.readStrongBinder());//读取参数
boolean _arg2;
_arg2 = (0!=data.readInt());//读取参数
int _result = this.startScan(_arg0, _arg1, _arg2);//调用服务端具体实现函数
reply.writeNoException();
reply.writeInt(_result);//返回给客户端的结果
return true;
}
............................
}
c) static class Proxy imp IXXX
服务端的代理类,跨进程通信中,客户端使用代理类proxy调用服务
int startScan(java.lang.String[] paths, com.miui.guardprovider.aidl.IVirusObserver virusObserver, boolean isCloud) 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.enforceInterface(DESCRIPTOR)
_data.writeStringArray(paths);//写入参数
_data.writeStrongBinder((((virusObserver!=null))?(virusObserver.asBinder()):(null)));写入参数
_data.writeInt(((isCloud)?(1):(0)));写入参数
mRemote.transact(Stub.TRANSACTION_startScan, _data, _reply, 0);//调用服务端的方法
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
总结一个完整的通信过程:
客户端进程得到Bp端引用,调用目标方法,目标方法中通过mRemote调用 transact()将目标函数的参数写入包裹,再通过底层binder驱动转发到服务端,经过OnTransact分发调用具体实现,最终调用到service中的具体业务实现。
1.2 客户端如何获得服务端的Binder对象引用
a)系统服务:使用getSystemService()方法获取的服务,系统服务一般不使用Service类实现,一般都是继承binder类。系统服务由ServiceManager来管理,系统服务在使用前向ServiceManager进行注册,客户端使用服务时向ServiceManager获取服务的引用。注意ServiceManager也是一个系统服务,它的代理架构跟其他系统服务一样的
b)应用程序自定义服务:客户端服务则必须基于Service类来编写,通过bindService获取相关服务的binder引用,asInterface提供了统一的查询接口,如果IPC通信,返回Proxy对象引用,如果进程内部使用服务则返回 Stub的具体实现类对象引用。
总结:两种获取方式最终都是通过AMS服务查询得到服务端的Binder引用
1.3 binder框架扮演的角色
binder框架在整个通信过程中不做具体的业务实现,整个框架只负责运输数据,将客户端的请求精确传达给服务端,同时将服务端的处理结果传递给客户端。只做数据传输不做具体业务,从而满足快进程通信。
1.4 Framework层的binder架构与native层的binder架构之间的关系
framework层的binder通过JNI调用native的binder架构,所以framework层(Java层)对native层(c/c++层)进行了一层包装,提供给应用层进行调用。native层binder是C/S架构,framework层的架构与相关类的设计原理与native层类似。所以理解了任意一层都很好理解另一层.
2.ContentProvider
2.1原理
ContentProvider底层实现是bin