参考:https://zhuanlan.zhihu.com/p/35519585
相比于其他IPC机制(Socket、共享内存):
相比于Socket(以及管道、信号量等),Binder少了一个copy(少了copy_to_user),因此更快
相比于共享内存,无需实现复杂的访问控制策略(锁)
当 A 进程想要获取 B 进程中的 object 时,驱动并不会真的把 object 返回给 A,而是返回了一个跟 object 看起来一模一样的代理对象Proxy,这个 Proxy 具有和 object 一摸一样的方法,但是这些方法并没有 B 进程中 object 对象那些方法的能力,这些方法只需要把把请求参数交给驱动即可。对于 A 进程(client)来说和直接调用 object 中的方法是一样的。
当 Binder 驱动接收到 A 进程的消息后,发现这是个 Proxy 就去查询自己维护的表单,一查发现这是 B 进程 object 的代理对象。于是就会去通知 B 进程调用 object 的方法,并要求 B 进程把返回结果发给自己。当驱动拿到 B 进程的返回结果后就会转发给 A 进程,一次通信就完成了。
IBinder : 是一个接口。只要类实现了这个接口,类的对象就能跨进程传输。下文简称IBinder接口的实现类的对象 为 IBinder对象
客户端调用bindService方法,接收服务端传递来的IBinder对象,存为IBinder对象serviceConnection
intent.setAction("com.baronzhang.ipc.server");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
IInterface : 是一个接口,代表Server 提供给Client的方法的集合
Binder : 一个类,实现了 IBinder 接口,Binder类对象应该出现在Server端
BookManager:Server端定义的接口,继承IInterface接口;定义Server端提供的功能,但不实现功能
其中功能方法的实现,在Server端新建的Stub对象中
Stub:AIDL生成的类,实现BookManager接口,继承Binder类
客户端和服务端均可调用Stub类的方法
Server端 在新建的Stub对象中,实现提供给Client端的功能方法
private final Stub bookManager = new Stub() {…………}
Client端 调用Stub类的静态方法asInterface,将Server端传递来的IBinder对象转换为Proxy对象
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
……
bookManager = Stub.asInterface(service);
……
}
……
}
其实,Proxy类只有两个成员变量:IBinder类对象remote,String类对象DESCRIPTOR(用于让Binder驱动 区分这个Proxy对象对应于哪个Binder Server)
private static final String DESCRIPTOR = "com.baronzhang.ipc.server.BookManager";
private IBinder remote;
所以只用IBinder对象service,就能初始化一个Proxy对象了
此外,服务端的Stub对象的onTransact()方法,会根据方法编号调用BookManager中的相关方法
Proxy:Server端定义的类,实现了BookManager接口
Server端将一个 IBinder的实现类的对象 (下文简称IBinder对象)传递给客户端,客户端利用此IBinder对象,创建Proxy对象类的实例出现在Client端,代表Server端的 Stub对象的代理
Proxy中实现的方法体,不实际处理任务,而是负责从客户端接收参数,交给服务端;再从服务端获取返回值,交给客户端
Binder、IBinder 和 IInterface 的关系:
参考https://blog.csdn.net/caoshen2014/article/details/99782563
参考:https://juejin.cn/post/6844903496882323464
AIDL:Android Interface Define Language
AIDL代码遵循Java语法
AIDL代码存放在AIDLmodule中的.aidl文件里,需要经过AS的编译,才能转换为Java代码
完整代码在:https://link.zhihu.com/?target=https%3A//github.com/BaronZ88/HelloBinder
IInterface : 是一个接口,代表Server 提供给Client的方法的集合
Binder : 一个类,实现了 IBinder 接口,Binder类对象应该出现在Server端
BookManager:Server端定义的接口,继承IInterface接口;定义Server端提供的功能,但不实现功能;
具体功能方法的实现,在Server端新建的Stub对象中
Stub:AIDL生成的类,实现BookManager接口,继承Binder类
客户端和服务端均可调用Stub类的方法。
Server端 在新建的Stub对象中,实现提供给Client端的功能方法
private final Stub bookManager = new Stub() {…………}
Client端 调用Stub类的静态方法asInterface,将Server端传递来的IBinder对象转换为Proxy对象
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
……
bookManager = Stub.asInterface(service);
……
}
……
}
其实,Proxy类只有两个成员变量:IBinder类对象remote,String类对象DESCRIPTOR(用于让Binder驱动 区分这个Proxy对象对应于哪个Binder Server)
所以只用IBinder对象service,就能初始化一个Proxy对象了
private static final String DESCRIPTOR = "com.baronzhang.ipc.server.BookManager";
private IBinder remote;
Proxy:Server端定义的类,实现了BookManager接口
Server端将一个 IBinder的实现类的对象 (下文简称IBinder对象)传递给客户端,客户端利用此IBinder对象,通过Stub.asInterface,创建Proxy对象:
类的实例出现在Client端,代表Server端的 Stub对象的代理
关于asInterface函数:
Proxy中实现的方法体,不实际处理任务,而是负责从客户端接收参数,交给服务端;再从服务端获取返回值,交给客户端
Stub类中,会对BookManager中的方法进行编号:
Proxy中调用transact进行分配:
private IBinder remote;
remote.transact(Stub.TRANSAVTION_getBooks, data, reply, 0);
最终调用到Stub的onTransact函数:
参考:https://blog.csdn.net/a372048518/article/details/75020240