写Binder是为了后面阅读四大组件启动过程,让心中有一个概念不至于分析不下去,因此只讲概念和流程不讲AIDL。
这里给一个大家公认的概念:
Binder是Android系统跨进程通信首选的一种方式。
那问题就来了
为什要跨进程通信?
为什么Binder是首选的一种方式?
Binder是什么?
Android中Binder机制?
为什么要跨进程?
进程空间划分
Android将进程空间划分为内核空间和用户空间,这两个空间进行交互需要通过系统调用。
内核空间:Android系统中只有一个内核空间,所有进程共用
用户空间:每个进程都有一个用户空间
进程隔离
Android为了保证安全性和独立性,将进程进行隔离,即一个进程不能直接访问或操作另一个进程。因此我们需要进行跨进程通信。
为什么Binder是首选的?
性能
1:Socket 作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。
2:消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。共享内存虽然无需拷贝,但控制复杂,难以使用。Binder只需要一次数据拷贝,性能上仅次于共享内存。
稳定
1:Binder 基于 C/S 架构,客户端(Client)有什么需求就丢给服务端(Server)去完成,架构清晰、职责明确又相互独立,自然稳定性更好。
2:共享内存虽然无需拷贝,但是控制负责,难以使用。从稳定性的角度讲,Binder 机制是优于内存共享的。
更安全
传统的 IPC 接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),从而无法鉴别对方身份。Android为每个安装好的APP分配了自己的UID,故而进程的UID是鉴别进程身份的重要标志。传统的IPC只能由用户在数据包中填入UID/PID,但这样不可靠,容易被恶意程序利用。
1:效率高:使用内存映射只需拷贝1次。
2:简单:面向对象调用方式。
3:稳定:基于 C/S 架构,职责明确、架构清晰稳定性好。
4:更安全:为每个 APP 分配 UID,用于鉴别身份。
Binder是什么?
直观来说Binder是Android中一个类,实现IBinder类。从IPC角度来说他是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟设备。从Framework层来说他是SM和其他Manager的桥梁。等等还有很多。
Binder原理和通信过程
Binder机制是Client-Server模式的。共涉及到4部分Client,Server,Binder驱动和SM(ServiceManager)。Binder驱动是一种虚拟的设备,主要用于连接其余的三部分,类似于桥梁的作用。ServiceManager用于管理系统中的各种服务。
内存映射
Binder机制中最终要的原理是内存映射通过mmap()来实现,mmap()是操作系统中一种内存映射的方法。内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。
一次完整的Binder通信过程
1:首先 Binder 驱动在内核空间创建一个数据接收缓存区.
2:接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系.
3:发送方进程通过系统调用copy_from_user()将数据copy到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
Android中Binder机制
Clietn:C/S中的C,消费服务的进程。
Server:C/S中的S,提供服务的进程。
ServiceManager:管理注册的Server,并提供Server的查询。它只提供路由功能。
Binder驱动:转发Client,Server和SM的请求。传递进程间的数据。
Android给我们封装好了Binder驱动和SM,所以我们只需要实现C和S就可以了。
大致步骤如下:
1:Server注册服务。
2:Client获取服务,此时Server和Client已经建立连接。
3:传递数据
Android给我们提供了AIDL来帮助我们实现Binder。AIDL涉及的比较多以后讲。