前言
作为一名Android开发者,想必大家都知道Android是基于Linux内核的!在Linux中,进程间通信有如下几种方式,管道、消息队列、共享内存、信号量、信号、Socket,但是Android却用Binder作为主要的进程间通信方式,这是为什么呢?下面让我们来分析下。
1 管道
管道是Linux一种常见的进程间通信方式,也是Linux最古老的一种进程间通信方式,管道分为匿名管道(PIPE)和命名管道(FIFO),它是Linux在内核开辟的一个具有固定大小的缓冲区(4k)。管道相当于我们日常生活中的一个水管,一端连接一个进程的输入,另一端连接一个进程的输出,下面我们来看下它的特点:
- 管道是半双工,同一时刻,数据只能向一个方向流通;如果双方需要相互通信,需要建立2个管道。
- 如果管道数据满了,写端进程会阻塞;如果为空,则读端进程会阻塞;如果读写进程终止,那管道会消失。
- 匿名管道只能在父子进程(或者兄弟进程)之间通信,而命名管道可以在任何进程之间通信。
缺点:数据拷贝多次,消耗CPU资源较大,缓冲区大小有限,所以管道并不适合Android进程间大量通信。
2 消息队列
消息队列提供了从一个进程向另外一个进程发送数据块的方法。每个数据块都被认为含有一个数据类型,接受进程可以独立的接受含有不同的数据类型。我们可以通过发送消息来避免命名管道的同步跟阻塞问题。但是消息队列跟管道一样,每个数据块都有一个最大的长度限制。
缺点:信息复制2次,额外的消耗CPU,有长度限制,并不适合Android进程间大量通信。
3 共享内存
共享内存就是在内存中开辟一段空间,供不同的进程访问。共享内存是正在运行的两个进程间共享和传递数据的一种有效方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到自己的地址空间,所有进程都可以访问共享内存中的地址。共享内存无需复制,直接附加到进程的虚拟地址空间,速度快。
缺点:无法保证各个进程间通信的有效性。进程间的同步问题操作系统无法实现,各个进程必须借助同步工具来解决。安全问题比较突出,如果将Android所有的app放到同一个共享内存,那后果不堪设想。
4 信号量
作为一种锁机制,防止一个进程在访问共享数据时,另外一个进程也访问该共享数据。常作为进程间或者同一进程中不同线程间的同步手段。
5 信号
不适合信息交换,适用于中断控制。比如非法内存访问、杀死某个进程。
6 Socket
网络套接字,作为不同机器或跨网络通信接口,其传输效率低,并不适合Android进程间大量通信。
上面对Linux自带的IPC进程了简单的介绍,接下来我们主要从如下几个角度来说明为什么Android将Binder作为主要的进程通信方式。
- 1 性能角度:消息队列和socket需要2此复制,管道需要多次复制,而Binder只需要一次复制,但是共享内存不需要复制,从性能角度来考虑,共享内存是要优于Binder的。
- 2 稳定性角度:Binder是基于C\S架构的,耦合性比较低,稳定性比较好;共享内存没有C\S架构,耦合性比较高,而且共享内存无法保证进程间的同步问题。所以从稳定性角度来说,Binder是要优于共享内存的。
- 3 安全性角度:传统Linux的IPC无法 获得对方进程的PID\UID,从而无法鉴别对象的身份。Android作为开源的OS,App来源广泛,如果不加鉴别的允许一些非法软件运行在用户的手机上,这将是非常危险的。
Android为每一个安装好的App分配自己的的UID,所以进程的UID是鉴别身份的重要标志,Binder是基于C\S架构的,对外只暴漏Client端,Client端将请求发送给Server端,Server根据权限控制策略,来判断UID\PID是否满足访问权限。从Android M开始,系统会弹出对话框来询问用户是否要给与权限,安全性极大的提高,所以从安全性角度来看Binder是要优于其他传统的IPC的。
总结
从上边分析我们可以得出,Google之所以将Binder作为Android主要的进程间通信方式,是因为它的稳定性跟安全性比传统的Linux中的IPC更好,性能也仅仅次于共享内存,所以Binder是不二选择。
欢迎关注我的微信公众号