目录
关于Linux进程间通信
Android系统基于Linux内核,而Linux内核继承和兼容了丰富的Unix系统进程间通信(IPC)机制。
有传统的管道(Pipe)、信号(Signal)和跟踪(Trace),这三项通信手段只能用于父进程与子进程之间,或者兄弟进程之间;后来又增加了命令管道(Named Pipe),使得进程间通信不再局限于父子进程或者兄弟进程之间;
为了更好地支持商业应用中的事务处理,在AT&T的Unix系统V中,又增加了三种称为“System V IPC”的进程间通信机制,分别是报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore);后来BSD Unix对“System V IPC”机制进行了重要的扩充,提供了一种称为插口(Socket)的进程间通信机制。
IPC | 数据拷贝次数 |
---|---|
Share Memory | 0 |
Binder | 1 |
Socket/Pipe/消息队列 | 2 |
Android考虑传输性能和安全性的要求,采用的是Binder。Binder基于 Client-Server通信模式,传输过程只需一次拷贝,为发送方添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。
Binder通信模型
Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制
在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序,其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间
核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。
Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件就可以了
Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系如下图所示:
Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中
Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信
Client和Server之间的进程间通信通过Binder驱动程序间接实现
Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力
关于Client-Server通信
Binder使用Client-Server通信方式. 通常要想实现Client-Server通信必须实现以下两点:
1) server 必须有确定的访问接入点或者说地址来接受Client的请求,并且Client可以通过某种途径获知Server的地址;
2) 制定Command-Reply协议来传输数据。
例如在网络通信中Server的访问接入点就是Server主机的IP地址+端口号,传输协议为TCP协议。对Binder而言,Binder可以看成Server提供的实现某个特定服务的访问接入点, Client通过这个‘地址’向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个 Server通信首先必须建立这个管道并获得管道入口。
面向对象思想之Binder
面向对象思想的引入将进程间通信转化为通过对某个Binder对象的引用调用该对象的方法,而其独特之处在于Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,而它的引用却遍布于系统的各个进程之中。这个引用和java里引用一样既可以是强类型,也可以是弱类型,而且可以从一个进程传给其它进程,让大家都能访问同一Server,就象将一个对象或引用赋值给另一个引用一样。
Binder 驱动
Binder驱动实际上和硬件设备没有关系,只是实现方式和设备驱动程序一样:它工作于内核态,提供open(),mmap(),poll(),ioctl()等标准文件操作,以字符驱动设备中的misc设备注册在设备目录 /dev下,用户通过/dev/binder访问它。
binder驱动在以misc设备进行注册,作为虚拟设备,没有直接操作硬件,只是对设备内存的处理。主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。
通过init(): 创建binder设备节点/dev/binder
通过open(): 获取binderdriver设备的文件描述符
通过mmap(): 在内核分配一块内存,存放数据
通过ioctl(): 将IPC数据作为参数,传递给binderdriver