当前位置:网站首页>【Android安全】Binder解析
【Android安全】Binder解析
2022-08-08 06:27:00 【Jouzzy】
参考:https://zhuanlan.zhihu.com/p/35519585
Binder一次copy的原理


相比于其他IPC机制
相比于其他IPC机制(Socket、共享内存):
相比于Socket(以及管道、信号量等),Binder少了一个copy(少了copy_to_user),因此更快
相比于共享内存,无需实现复杂的访问控制策略(锁)

Binder代理机制
当 A 进程想要获取 B 进程中的 object 时,驱动并不会真的把 object 返回给 A,而是返回了一个跟 object 看起来一模一样的代理对象Proxy,这个 Proxy 具有和 object 一摸一样的方法,但是这些方法并没有 B 进程中 object 对象那些方法的能力,这些方法只需要把把请求参数交给驱动即可。对于 A 进程(client)来说和直接调用 object 中的方法是一样的。
当 Binder 驱动接收到 A 进程的消息后,发现这是个 Proxy 就去查询自己维护的表单,一查发现这是 B 进程 object 的代理对象。于是就会去通知 B 进程调用 object 的方法,并要求 B 进程把返回结果发给自己。当驱动拿到 B 进程的返回结果后就会转发给 A 进程,一次通信就完成了。
Java层Binder的各个类和接口
IBinder : 是一个接口。只要类实现了这个接口,类的对象就能跨进程传输。下文简称IBinder接口的实现类的对象 为 IBinder对象
客户端调用bindService方法,接收服务端传递来的IBinder对象,存为IBinder对象serviceConnectionintent.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
关于AIDL
参考:https://juejin.cn/post/6844903496882323464
AIDL:Android Interface Define Language
AIDL代码遵循Java语法
AIDL代码存放在AIDLmodule中的.aidl文件里,需要经过AS的编译,才能转换为Java代码
Java层Binder实例代码分析
完整代码在: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函数:
Native层Binder实现
参考:https://blog.csdn.net/a372048518/article/details/75020240

鸡生蛋问题
参考https://www.jianshu.com/p/062a6e4f5cbe
ServiceManager和Binder驱动属于两个不同的进程,它们是为Client和Server之间的进程间通信服务的,也就是说Client和Server之间的进程间通信依赖ServiceManager和Binder驱动之间的进程间通信,这就像是:“蛋生鸡,鸡生蛋,但第一个蛋得通过一只鸡孵出来”。Binder机制是如何创造第一只下蛋的鸡呢?
当Android系统启动后,会创建一个名称为servicemanager的进程,这个进程通过一个约定的命令BINDERSETCONTEXT_MGR向Binder驱动注册,申请成为ServiceManager,Binder驱动会自动为ServiceManager创建一个Binder实体(第一只下蛋的鸡);
并且这个Binder实体的引用在所有的Client中都为0,也就说各个Client通过这个0号引用就可以和ServiceManager进行通信。Server通过0号引用向ServiceManager进行注册,Client通过0号引用就可以获取到要通信的Server的Binder引用。
边栏推荐
猜你喜欢
随机推荐
[Unity] GPU动画实现(四)——生成动画数据
使用js写一个2048
【Unity】unity中对象池的使用
Leetcode topic sharing and explanation
反射,魔法方法,元类相关知识点总结
tcpdump进行DNS抓包
tcpdump进行ARP抓包
栈队列OJ题分享及讲解
win11+MX250+CUDA Tookit 10.1 update 2
Lettcode linked list OJ question sharing and explanation
Unity中获取一个物体下所有的子物体的方法
golang 服务大量 CLOSE_WAIT 故障排查
带头双向循环链表的增删查改
万级TPS亿级流水-中台账户系统架构设计
Unity 本地 IIS 服务搭建之文件夹权限配置
Nine common interfaces for implementing sequence table in C language
Makefile文件的编写(实例详解)
排列组合题目小结
关于在finally代码块中修改try代码块中基本数据类型返回值的问题
Implementation of bubble sort in C language and optimization of bubble sort









