Binder机制
Binder机制
Binder概述
Binder是Android专有的一种IPC机制,它基于开源的OpenBinder实现。相比Linux已有的IPC方式(如管道、消息队列、共享内存等),Binder具有以下优势:
- 性能高效:只需一次数据拷贝
- 安全性好:为每个App分配UID,进行有效性检测
- 使用简单:采用面向对象的思想,调用方式类似调用本地对象
Binder架构
Binder采用C/S架构,主要由以下几部分组成:
- Client:使用服务的客户端
- Server:提供服务的服务端
- ServiceManager:管理服务的注册和查询
- Binder驱动:运行在内核空间,负责进程间Binder通信的建立
Binder通信原理
Binder的通信过程大致如下:
- Server向ServiceManager注册服务
- Client向ServiceManager查询服务
- ServiceManager返回服务的Binder代理给Client
- Client通过Binder代理发起远程调用
- Binder驱动将数据从Client进程拷贝到Server进程
- Server处理请求,并将结果返回
整个过程中,Binder驱动起着至关重要的作用,它利用内存映射(mmap)来实现零拷贝,大大提高了效率。
内存映射的建立:
零拷贝的实现:
- 发送数据时,发送进程将数据写入映射的用户空间内存
- 由于该内存同时映射到内核空间,Binder驱动可以直接访问这些数据,无需额外拷贝
- 接收进程的用户空间也映射了同一块物理内存,因此可以直接读取数据,再次避免了拷贝
这种机制将传统IPC的两次拷贝(用户空间到内核空间,再到另一个用户空间)减少为一次,大大提高了数据传输效率
Binder在Android中的应用
Binder机制在Android系统中应用广泛,主要体现在:
- 系统服务:如AMS、WMS等都基于Binder实现
- 四大组件:组件间的通信都依赖Binder
- AIDL:跨进程接口定义语言,底层就是Binder
- ContentProvider:底层通过Binder实现数据共享
Binder相比其他IPC机制的优势
Binder | 共享内存 | Socket | |
---|---|---|---|
性能 | 需要拷贝一次 | 无需拷贝 | 需要拷贝两次 |
特点 | 基于C/S架构,易用性高 | 控制复杂,易用性差 | 基于C/S 架构 作为一款通用接口,其传输 效率低,开销大 |
安全性 | 为每个APP分配UID,同时支持实名和匿名 | 依赖上层协议,访问接入点是开放的,不安全 | 依赖上层协议,访问接入点是开放的,不安全 |
Binder 如何做到一次拷贝?
内核空间通过系统调用将A进程用户空间的数据复制一份到内核空间(copy from user);
内核空间的虚拟内存 最终都必须要关联到同一个物理内存「所有app的内核空间都映射同一个物理空间」(利用 MMU,将虚拟内存转换成物理内存);
内核空间将数据放到内核空间的虚拟内存,内核空间的这个虚拟内存映射的物理内存地址和接收方 B 进程的用户空间中虚拟内存映射的物理内存地址是同一个(如何映射:通过 mmap(零拷贝技术) 来完成映射);
内核往里面放,就相当于放到了 B 进程用户空间的虚拟内存中,B 进程可直接访问;
还不明白看下文
而在Binder中,整体通信机制和传统IPC一样,那么为何能实现一次copy,这是因为在物理内存的指向上做了改动。
在Binder中,内核空间和进程2中分别另外开辟了一块虚拟内存,这两块虚拟内存指向物理内存中的同一块内存空间。然后传递数据的时候,将数据从进程1的物理内存1中复制到内核空间和进程2共同指向的物理内存块中,也就是下图物理内存中的紫色部分。这样进程2中就获取到了数据。这样就实现了一次copy。
MMAP原理
Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)。
对文件进行mmap,会在进程的虚拟内存分配地址空间,创建映射关系。实现这样的映射关系后,就可以采用指针的方式读写操作这一段内存,而系统会自动回写到对应的文件磁盘上。
写文件流程:
1. 调用write,告诉内核需要写入数据的开始地址与长度 。
2. 内核将数据拷贝到内核缓存 。
3. 由操作系统调用,将数据拷贝到磁盘,完成写入
参考文档: