基础知识
进程空间划分
- 一个进程空间分为用户空间与内核空间。用户空间与内核空间都是虚拟内存,映射到物理内存。所有进程的内核空间映射到同一块物理内存,是共享的
- 二者区别:
- 进程间,用户空间的数据不可共享,即用户空间=不可共享空间
- 进程间,内核空间的数据可共享,所以内核空间=可共享空间
- 进程内用户空间与内核空间进行交互需要系统调用,主要函数
- copy_from_user():将用户空间的数据拷贝到内核空间
- copy_to_user():将内核空间的数据拷贝到用户空间
传统的进程间通讯方式
Android基于Linux内核,Linux进程通讯方式有socket、共享内存、管道、信号量等
工作流程:
- 发送数据:通过系统调用copy_from_user()将数据从用户空间copy到内核缓存区
- 接收数据:通过系统调用copy_to_user()将数据从内核空间copy到用户空间
缺点:
- 效率低下,需要做两次数据拷贝。用户空间->>内核空间->>用户空间
- 接收数据的缓存由接收方提供,接收方不知道需要多大缓存
Binder
Binder 是什么
以我的理解,binder 是client、service与ServiceManager沟通的桥梁,是一种类似驱动的存在
与其他IPC对比
- 从性能的角度:Binder数据拷贝只需要一次,而管道、消息队列、Socket需要2次,但共享内存方式一次内存拷贝都不需要;从性能角度看,Binder性能仅次于共享内存。
- 从稳定性的角度:Binder是基于C/S架构的,稳定性较好;共享内存实现方式复杂,没有客户与服务端之别, 需要充分考虑到访问临界资源的并发同步问题,否则可能会出现死锁等问题;从这稳定性角度看,Binder架构优越于共享内存。(PS:简单解释下C/S架构,是指客户端(Client)和服务端(Server)组成的架构,Client端有什么需求,直接发送给Server端去完成,架构清晰明朗,Server端与Client端相对独立,稳定性较好)
- 从安全的角度:传统Linux IPC的接收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份;而Android作为一个开放的开源体系,拥有非常多的开发平台,App来源甚广,因此手机的安全显得额外重要;对于普通用户,绝不希望从App商店下载偷窥隐射数据、后台造成手机耗电等等问题,传统Linux IPC无任何保护措施,完全由上层协议来确保。Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志