参考资料:
几种进程通信方式的对比总结
Android Binder 机制(一) Binder 的设计和框架
Android 面试收集录14 Android 进程间通信方式
一篇文章了解相见恨晚的 Android Binder 进程间通讯机制
Broadcast、AIDL、ContentProvider、Messager的区别和适用场景
Binder 是 Android 系统中进程间通讯( IPC )的一种方式,也是 Android 系统中最重要的特性之一。Android 中的四大组件 Activity , Service , Broadcast , ContentProvider ,不同的 App 等都运行在不同的进程中,它是这些进程间通讯的桥梁。正如其名“粘合剂”一样,它把系统中各个组件粘合到了一起,是各个组件的桥梁。
Binder 通信采用 C-S 架构,它包含 Client、 Server、 ServiceManager 以及 Binder 驱动这四个组件,它们的工作就是让 Client 和 Server 进行通信。
如果 C-S 架构中的 Client 和 Server 属于同一进程的话,那么 Client 和 Server 之间的通信就非常容易。只需要在 Client 端先获取相应的 Server 端对象,再通过 Server 对象调用 Server 的相应接口即可。
但是,Binder 机制中涉及到的 Client 和 Server 是位于不同的进程中的,这就意味着,不可能直接获取到 Server 对象。
怎么办呢?
解决方法是为 Client 提供一个 Server 的远程服务作为代理。Client 要和 Server 通信时,只需要调用该代理的相应接口,其作用就相当于直接拿到 Server 的对象。
那么这个远程服务是如何帮 Client 代理的呢?
首先我们要知道 Linux 系统下的内存划分为用户空间和内核空间。
用户空间和内核空间
用户空间是应用程序的运行空间,内核空间是 Linux 内核的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。
用户空间不能直接调用系统资源,必须通过系统接口,才能向内核发出指令,而内核空间可以执行任意命令,调用系统的一切资源。
由于应用程序都运行在用户空间,并且互相隔离,所以如果不同的应用程序之间需要通信,则必须通过内核空间进行中转。这就好比以前不同地方的两个人通信需要借助邮局来传递信件一样。
在上述 Binder 的四个组件中,Client 和 Server 位于用户空间,而 Binder 驱动位于内核空间,所以 Binder 驱动就扮演了“邮局”这样一个负责中转的角色。
在 Binder 驱动中,存在着一个个 Binder 实体,每一个 Binder 实体都保存了对应的 Server 的信息。
ServiceManager 是一个特殊的 Server,负责 Server 的注册与查询,它在系统开机时启动。
ServiceManager 中有一棵红黑树,用于存放 Binder 驱动中 Binder 实体的引用。Server 注册时,Binder 驱动会新建一个 Binder 实体,并在这棵树中添加该实体的引用。Server 的查询时,便是在这棵树上进行的。
当应用程序启动时,ServiceManager 会和 Binder 驱动进行通信,告诉 Binder 驱动它是服务管理者。随后,Binder 驱动会为 ServiceManager 创建对应 Binder 实体,并将该 Binder 实体设为全局变量。方便后面 Client 和 Server 与 ServiceManager 进行通信。
上面说到,Client 要和 Server 通信,需要通过 Server 的远程服务作为代理。那么 Client 是如何获取到 Server 的远程服务的呢?
Client 首先会向 Binder 驱动发起获取服务的请求。Binder驱动在收到该请求之后会将该请求转发给 ServiceManager 进程。随后,ServiceManager 会根据 Client 提供的 Server 的服务名,从红黑树中找到对应 Server 的引用信息,并将其返回给 Client 。
Client 收到 Server 对应的 Binder 引用信息之后,就根据该 Binder 引用信息创建一个与 Server 对应的远程服务,这个远程服务就是我们所说的代理。
Client 通过调用该远程服务的接口,就相当于在调用 Server 的服务接口一样。因为 Client 调用该 Server 的远程服务接口时,该远程服务会通过 Binder 驱动的 Binder 实体连接到真正的 Server 进行交互,从而执行相应的动作。
1.应用启动
ServiceManager -> Binder 驱动创建全局的 Binder 实体
2.Server注册
Server -> Binder 驱动创建 Binder 实体 -> ServiceManager 添加 Binder 引用
3.Client 与 Server 通信
Client -> Server 的远程服务 -> Binder 实体 -> Server
Android Framework 层对 Binder 使用的封装,方便开发者使用。
Server 端每收到一个请求,就会启动一个线程去响应。
Client 端获取返回值是同步的。
AIDL 的进一步封装,以串行的方式处理客户端发来的消息。
Server 端收到的请求都会放在 Handler 的 MessageQueue 里面。
Client 端获取返回值是异步的。
AIDL 的封装,可以实现在应用程序中共享数据,并提供增删改查的功能。
通过文件共享信息,如 SharedPreferences 。
通过序列化对象到文件中,从文件中反序列化恢复对象。
通过 socket 实现一对一的网络传输。