Linux现有的所有进程间IPC方式:
- 管道:在创建时分配一个page大小的内存,缓存区大小比较有限;
- 消息队列:信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信;
- 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决;
- 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信;
- 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;
Android使用Binder而不使用Linux自有的IPC方式的原因:
(1)从性能角度
Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要两次,但是共享内存一次拷贝都不需要;从这块分析,Binder的性能是只在共享内存之后
(2)从稳定性角度
Binder是基于C/S架构,server端和client端相对独立,稳定性较好;而共享内存实现方式比较复杂,没有客户端和服务端的区别,需要充分考虑到临界资源的并发同步问题,否则可能会出现死锁;稳定性上Binder是优于共享内存。
(3)从安全角度
传统的Linux IPC方式无法获得对方进程可靠的UID/PID,从而无法鉴别对方的身份;而Android为每个安装好的应用都分配了自己的UID,所以进程的UID是鉴别进程身份的一个重要的标志,Android系统中对外只是暴露了client端,而client发送数据到server端的时候,server端就会根据权限控制策略判断UID/PID是否满足权限,这块其实就类似于Android6.0开始的权限访问控制。
而传统的IPC方式,只能由用户在数据包里填入UID/PID;并且可靠的身份标记只有由IPC机制本身在内核中增加。其次传统IPC访问接入点是开放的,无法建立私有通道。从安全角度,Binder的安全性更高。
(4)从语言层面角度
大家多知道Linux是基于C语言(面向过程的语言),而Android是基于Java语言(面向对象的语句),而对于Binder恰恰也符合面向对象的思想,将进程间通信转化为通过对某个Binder对象的引用调用该对象的方法,而其独特之处在于Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,而它的引用却遍布于系统的各个进程之中。可以从一个进程传给其它进程,让大家都能访问同一Server,就像将一个对象或引用赋值给另一个引用一样。Binder模糊了进程边界,淡化了进程间通信过程,整个系统仿佛运行于同一个面向对象的程序之中。
比如在Android OS中的Zygote进程的IPC采用的是Socket(套接字)机制,Android中的Kill Process采用的signal(信号)机制等等。而Binder更多则用在system_server进程与上层App层的IPC交互。
网友评论