Framework篇 - Android 为何选择 Binder 以及 Binder 的实现原理

无论是什么 OS,各个组件都运行在不同的进程/线程内,这就会涉及到它们之间的通信问题。Linux 现在已有的 IPC 通信方式有管道、信号量、信号、消息队列、共享内存、Socket 套接字,而 Android 在 Linux 的基础上还有自己独特的 Binder IPC 机制。

Android OS 中的 Zygote 进程的 IPC 采用的是 Socket 机制,在上层 system server、media server 以及 App 之间更多的是采用 Binder IPC 方式来完成跨进程间的通信。对于 Android 上层架构中,很多时候是在同一个进程的线程之间需要相互通信, 例如同一个进程的主线程与工作线程之间的通信,往往采用的 Handler 消息机制。当然也有少量其他的 IPC 方式,比如杀进程Process.killProcess() 采用的是 signal 方式。

 

目录:

  1. IPC 与 RPC
  2. Linux 的 IPC 通信方式
  3. 为什么选择 Binder
  4. Binder 的实现原理 

 

 

1. IPC 与 RPC

本地过程调用 (IPC) IPC 用在多任务操作系统中,使得同时运行的任务能互相会话。这些任务共享内存空间使任务同步和互相发送信息。

远程过程调用 (RPC) RPC 类似于 IPC,只是在网上工作。RPC 开始是出现在 Sun 微系统公司和 HP 公司的运行 UNIX 操作系统的计算机中。

通过 IPC 和 RPC,程序能利用其它程序或计算机处理的进程。客户机/服务器模式计算把远程过程调用与其它技术如消息传递一道, 作为系统间通信的一种机制。

 

 

2. Linux 的 IPC 通信方式

  • 1. 管道:在创建时分配一个 page 大小的内存,缓存区大小比较有限;
  • 2. 消息队列:信息复制两次,额外的 CPU 消耗,不合适频繁或信息量大的通信; 
  • 3. 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快。但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决; 
  • 4. 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信; 
  • 5. 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。 
  • 6. 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;

 

 

3. 为什么选择 Binder

  • 1. 从性能的角度 数据拷贝次数:Binder 数据拷贝只需要一次,而管道、消息队列、Socket 都需要2次,但共享内存方式一次内存拷贝都不需要。从性能角度看,Binder 性能仅次于共享内存。
  • 2. 从稳定性的角度 Binder 是基于 C/S 架构的,简单解释下 C/S 架构,是指客户端 (Client) 和服务端 (Server) 组成的架构,Client 端有什么需求,直接发送给 Server 端去完成,架构清晰明朗,Server 端与 Client 端相对独立,稳定性较好。而共享内存实现方式复杂,没有客户与服务端之别,需要充分考虑到访问临界资源的并发同步,否则可能会出现死锁等问题。从这稳定性角度看,Binder 架构优越于共享内存。

从以上两点,各有优劣,但还不足以支撑 Google 去采用 Binder 的 IPC 机制,那么更重要的原因是:

  • 1. 从安全的角度传统 Linux IPC 的接收方无法获得对方进程可靠的 UID/PID,从而无法鉴别对方身份。而 Android 作为一个开放的开源体系,拥有非常多的开发平台,App 来源甚广,因此手机的安全显得额外重要。对于普通用户,绝不希望从 App 商店下载偷窥隐射数据、后台造成手机耗电等等问题,传统 Linux IPC 无任何保护措施,完全由上层协议来确保。 Android 为每个安装好的应用程序分配了自己的 UID,故进程的 UID 是鉴别进程身份的重要标志,前面提到 C/S 架构,Android 系统中对外只暴露 Client 端,Client 端将任务发送给 Server 端,Server 端会根据权限控制策略,判断 UID/PID 是否满足访问权限,目前权限控制很多时候是通过弹出权限询问对话框,让用户选择是否运行。
  • 2. 从语言层面的角度大家多知道 Linux 是基于 C 语言(面向过程的语言),而 Android 是基于 Java 语言(面向对象的语句),对于 Binder 恰恰也符合面向对象的思想,将进程间通信转化为通过对某个 Binder 对象的引用调用该对象的方法,而其独特之处在于 Binder 对象是一个可以跨进程引用的对象,它的实体位于一个进程中,而它的引用却遍布于系统的各个进程之中。可以从一个进程传给其它进程,让大家都能访问同一 Server,就像将一个对象或引用赋值给另一个引用一样。Binder 模糊了进程边界,淡化了进程间通信过程,整个系统仿佛运行于同一个面向对象的程序之中。从语言层面,Binder 更适合基于面向对象语言的 Android 系统,对于 Linux 系统可能会有点"水土不服"。同时在 Android 系统中也依然采用了大量 Linux 现有的 IPC机制,根据每类 IPC 的原理特性,因时制宜,不同场景特性往往会采用其下最适宜的。比如在 Android OS 中的 Zygote 进程的 IPC 采用的是 Socket 套接字机制,Android 中的 Kill Process 采用的 signal (信号) 机制等。而 Binder 更多则用在system server 进程与上层 App 层的 IPC 交互。

 

 

4. Binder 的实现原理

 

  • 4.1 内核空间与用户空间

每个 Android 进程,只能运行在自己进程所拥有的虚拟地址空间。对应一个 4GB 的虚拟地址空间,其中 3GB 是用户空间,1GB是内核空间,当然内核空间的大小是可以通过参数匹配调整的。对于用户空间,不通进程之间是不能共享的,而内核空间的内存是可以共享的。Client 进程向 Server 进程通信,恰恰是利用进程间可共享的内核内存空间来完成底层通信工作的,Client 端与Server 端进程往往采用 ioctl 等方法跟内核空间的驱动进行交互。

 

  • 4.2 Binder 的原理


可以看出无论是注册服务和获取服务的过程都需要 ServiceManager,需要注意的是此处的 ServiceManager 是指 Native 层的ServiceManager (C++), 并非指 Framework 层的 ServiceManager (Java)。ServiceManager 是整个 Binder 通信机制的大管家,是 Android 进程间通信机制 Binder 的守护进程, 要掌握 Binder 机制,首先需要了解系统是如何首次启动 ServiceManager。当ServiceManager启动之后,Client 端和 Server 端通信时都需要先获取 ServiceManager 接口,才能开始通信服务。

  • 注册服务 (addService):Server 进程要先注册 Service 到 ServiceManager。该过程:Server 是客户端,ServiceManager 是服务端。
  • 获取服务 (getService):Client 进程使用某个 Service 前,须先向 ServiceManager 中获取相应的 Service。该过程:Client 是客户端,ServiceManager 是服务端。
  • 使用服务:Client 根据得到的 Service 信息建立与 Service 所在的 Server 进程通信的通路,然后就可以直接与 Service 交互。该过程:Client 是客户端,Server 是服务端。

Client,Server,Service Manager 它们之间是不直接交互的,而是通过与 Binder 驱动进行交互,从而实现 IPC 通信方式。 其中Binder 驱动位于内核空间,Client,Server,Service Manager 位于用户空间。Binder 驱动和 Service Manager 可以看做是Android 平台的基础架构, 而 Client 和 Server 是 Android 的应用层,开发人员只需自定义实现 Client、Server 端,借助 Android的基本平台架构便可以直接进行 IPC 通信。

 

  • 4.3 C/S 模式

BpBinder (客户端) 和 BBinder (服务端) 都是 Android 中 Binder 通信相关的代表,它们都从 IBinder 类中派生而来,关系图如下:

Client 端:BpBinder.transact() 来发送事务请求。

Server 端:BBinder.onTransact() 会接收到相应事务。

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值