Linux IPC方式:
1.管道:
管道是由内核管理的一个缓冲区,它只支持半双工通信,数据只能单向流动,大小只有4KB
当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。
当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。
当两个进程都终结的时候,管道也自动消失。
匿名管道: 只支持父子或兄弟进程之间的通信
命名管道: 支持无亲缘关系的进程通信
缺点: 半双工,容量小,不适合频繁的进程通信,或数据量较大的数据通信
2.信号量:
信号量是一个计数器,常作为一种同步或互斥机制,防止某进程正在访问共享资源时,其他进程也访问该资源
3.消息队列:
消息队列与命名管道类似,每个数据块都有一个最大长度的限制。
它是内核中的一条由消息组成的链表,信息复制两次;不合适频繁或信息量大的通信;
4.共享内存:
共享内存由一个进程在内核空间创建,可以被多个进程访问,是最快的IPC方式,消息无需复制
最大的缺点是,进程同步问题和安全问题,需要复杂的同步互斥逻辑去管理
5.套接字:
传输效率低,主要用于不通机器或跨网络的通信,信息需要拷贝两次
总结:
跨进程通信都需要内核空间
的支持;
管道、消息队列、Socket都需要2次拷贝
:进程A拷贝信息到内核空间,内核空间再拷贝信息到进程B
2.Binder IPC:
Android进程通信涉及到四个对象,分别是Client进程
,Server进程
,Binder驱动
,ServiceManager进程
,其中Binder驱动和ServiceManager进程属于Android基础架构,系统已经实现好了;
Server进程会创建多个线程来处理Binder请求,一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程
1.Binder IPC过程:
1.注册服务:
Service进程通过Binder驱动向ServiceManager注册
服务,Service对应的Binder实体存储在ServiceManager中,通过这个Binder可以向Service进程发出请求
2.获取服务:
Client进程向通过Binder驱动向ServiceManager查询
自己需要的服务,ServiceManager查到所需服务对应的Binder信息,通过Binder驱动给Client进程返回这个Binder的代理
对象,这时Client进程与 Server进程就建立了连接
3.使用服务:
Client进程通过Binder代理发送要调用的方法和参数,Binder驱动通过Binder向对应Service发出请求,Service根据方法名和参数计算出结果后,再通过Binder驱动把结果返回给Client进程
2.内存映射:
内存映射的意思是,用户空间有一个虚拟地址A,内核空间有一个虚拟地址B,通过某种方法这个虚拟地址A和B映射到内核中同一块物理地址,这样虚拟地址A和虚拟地址B对应的内存就同时被改变了,从而省去了一次数据拷贝;
Binder通过内存映射mmap
使得IPC过程只发生一次数据拷贝,提高了数据传输效率;
内存映射的规则表明,每个进程占用的内存有一部分在内核空间
,且大小默认为1M-8K这么大
3.Binder通信的优点:
1.效率高:
Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次拷贝,但共享内存方式一次内存拷贝都不需要;从性能角度看,Binder性能仅次于共享内存;
2.稳定性
Binder是基于C/S架构的,稳定性较高,使用简单
3.安全性
传统Linux IPC的接收方无法获得对方进程可靠的PID,从而无法鉴别对方身份;
Android为每个安装好的应用程序分配了自己的UID,可以鉴别对方身份;