最近重新复习Android Binder知识,以下为笔记内容,方便自己后序复习
Linux 进程的通信方式:
1. 管道:分一个page页的内存,传递消息,空间不足,需要复制两次
2. 共享内存: 分配一块空间作为共享空间,不需要复制,但是需要同步机制
3. socket: 套接字,效率低,需要复制两次
4. 信息队列: 需要复制一次进内核空间,再复制出用户空间,需要复制两次
5. 信号量: 资源互斥,锁机制
6. 信号: 一般作为中断控制,杀死进程等
binder
![binder][1]
为什么采用binder?
binder只需要复制一次数据到内核空间,只比共享内存多一次。
Linux的IPC机制无法获得进程的UID/PID等,所以无法鉴别身份。
Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。
binder功能
- 使用驱动进行进程通信
- 使用共享内存提高性能
- 为进程请求提供线程池处理
- 同步调用
- 面向对象的处理方式,对其他进程的通信操作转而对binder对象的引用的操作
原理
binder使用client-servier的模式
- client
- server
- binder驱动
- serviceManager
其中client和server、serviceManager是运行在用户空间,binder驱动是允许在内核空间。
binder驱动和设备驱动一样吗?
不一样,binder驱动只是内核空间的一段代码,负责在用户空间和内核控件来回搬运数据。
binder驱动的功能
- 负责建立binder节点对象
- 负责进程间传递binder对象
- 使用引用计数法
- 数据包在进程传递交互
- 建立和管理缓存空间
serviceManager
- 负责管理service系列,整个系统只有一个serviceManager进程,与
- 通过向binder驱动发送BINDER_SET_CONTEXT_MGR命令使其成为serviceManager,获得的句柄是0,binder建立一个结点(binder_node),addService()
- 进入无限的循环,等待client的请求
- 将client持有的字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用
server
- 提供服务的server通过binder驱动,获取0号句柄,向serviceManager注册自己的binder实体和名字。
- Binder是一个实体位于Server中的对象
client
- Client利用0号引用向SMgr请求访问某个Binder
- Binder 在Client端的表述 – Binder引用
binder协议
binder协议主要通过icotl()函数来实现,命令+数据
binder缓存
- 由Binder驱动负责管理数据接收缓存,使用mmap()命令,映射
- 创建一个数据接收的缓存空间,mmap分配的内存是在数据的接收方上。
- binder驱动负责创建和管理缓存空间,使用最佳分配算法为数据包分配一个空间,而接收方只需要提供缓存来存放大小固定,可以预测的消息头。
- 由于mmap()分配的内存是映射在接收方用户空间里的,所有数据只做了一次从发送方用户空间到接收方用户空间的直接数据拷贝,省去了内核中暂存这个步骤,提升了一倍的性能。
- Linux内核实际上没有从一个用户空间到另一个用户空间直接拷贝的函数,需要先用copy_from_user()拷贝到内核空间,再用copy_to_user()拷贝到另一个用户空间。为了实现用户空间到用户空间的拷贝,mmap()分配的内存除了映射进了接收方进程里,还映射进了内核空间。
binder线程管理
- 线程迁移: client端的线程A通过binder引用请求server端,server端会有一个线程B执行任务,执行完后会唤醒A,B相当于A代理执行任务,会将A的优先级付给B。
- server端:线程池
参考:
http://www.jianshu.com/p/6546a2ef0bca
https://www.zhihu.com/question/39440766
[1]: http://img.blog.csdn.net/20141126170909147?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlubWlhbnNoZW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center