什么是binder
- 通常意义下,binder指的是一种通信机制
- 对Server端来说,Binder指的是Binder本地对象,对于Client端来说,Binder指的是Binder代理对象
- 对于传输过程而言,binder是可以跨进程传输的对象
Binder的基本原理
Binder借助了内存映射(mmap)的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射。从发送方用户空间拷贝到内核空间缓存区的数据,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝。
传统Linux IPC机制的缺点
1.1 性能角度
管道、消息队列、Socket实现一次进程通信都需要2次内存拷贝,效率太低;
共享内存虽然不需要拷贝内存,但管理复杂;
Binder只需要一次内存拷贝,从性能角度来看,低于共享内存方式,优于其它方式。
IPC | 数据拷贝次数 |
---|---|
share mm | 0 |
Binder | 1 |
pipe MQ SOCKET | 2 |
binder通信模型
1. 通讯录: ServiceManager
通讯录中保存了每一个人的信息和号码,可以方便去查询。A通过查找B的号码就可以方便的与B进行通讯;
2. 基站:binder驱动
两个人通信不但需要知道号码,还必须有基站的支持才能打电话; 类比到binder机制,两个用户空间的进程,想要通信不但需要通过ServiceManager这个通讯录查找到对方,还需要一个运行在内核空间的基站即binder驱动来完成转发。
binder通信模型
看下面这张图
第一步: ServiceManger的建立,前面说过ServiceManger相当于通讯录,所以说首先要有一个进程向驱动提出申请为ServiceManager,而内核驱动同意后,ServiceManager就负责管理所有的通信号码,这时候还没有人向ServiceManger中注册号码,所以说这时候号码是没有的;
第二步: A同学想要联系B同学,就必须将自己的号码注册到ServiceManager,在每个同学的进程启动之后,随即就会向ServiceManager进行报告,ServiceManager会存储同学的名称以及号码(就是服务的名称和内存地址)。ServiceManger中会建立一张表对应各个同学的名字和电话号码
第三步:就是图中client想要跟Server2通信,需要先通过ServiceManager查询Server2的号码,然后Client就可以通过binder与Server2进行通信了;
binder如何实现跨进程通信
假设client想要调用Server端的add方法,这就是一个跨进程通信的调用;
首先:Server会把自己注册到ServiceManager的查询表中 然后:Client开始查询ServiceManger,拿到Server的代理对象;为什么是代理对象,因为client和server都是在用户空间,binder驱动是在内核空间 无法返回一个真正的server对象,只能返回代理对象,这一层封装对于client是透明的。
以上就是Android中的binder通信的原理;Android的进阶之路还有很多要学习的知识。把这些归纳成一个文档《Android核心技术手册》里面包含30多个技术模块。可以帮助你在Android开发进阶起到效果。需要可以点击前往。
总结
Server端把自己注册到ServiceManager,而Client端想要调用Server端的一个方法比如add方法,它会到ServiceManager中去查询是否有这样的一个方法; 这时候ServiceManager会返回给Client端一个代理对象的add方法,但这个add方法是一个空方法,什么都做不了; 空方法的主要作用是当client端调用add方法时,会返回给内核驱动; 内核驱动接收到了代理对象的add方法,它就知道client端想要调用的是Server端的add方法,这时候内核驱动会去调用Server端的add方法,然后Server端的add方法调用完之后,把结果返回给内核驱动层的ServiceManager,然后ServiceManager再把结果返回给Client,这样就是一个完整的binder跨进程通信原理。
客户端只不过是持有了服务端的代理对象,然后通过代理对象协助驱动去跨进程通信。