Android Binder 的主要内容概述以及特性和原理

本文深入探讨了Android Binder的由来、特性和原理,它作为Android独有的IPC方式,相比Linux传统IPC在性能、稳定性和安全性上有显著优势。Binder仅需一次数据拷贝,具有清晰的C/S架构,支持身份验证,提供实名和匿名Binder,确保了高效且安全的跨进程通信。

Binder在Android中有举足轻重的地位,不管是Activty的启动流程,还是四大组件的通讯方式都一一和binder有着细密的关联。 主要从四个大方向介绍Binder:

  • Binder由来和特性:首先是对Binder有个完整的认识和他存在的优势分析

  • Linux下IPC原理:Android是基于Linux的,所以先了解下Linux固有的进程通讯的方式有助于对Binder的理解

  • Binder原理:主要包括组件的构成、架构和通讯原理

  • Binder有关的常见问题:一些常见的和不常见的有关Binder的问题有助于更好的理解和加深对Binder的认识

[](()二、Binder概述


[](()1.什么是Binder?

  • 从IPC角度来说:Binder是Android中的一种跨进程通信方式,该通信方式在linux中没有,是Android独有;

  • 从Android Driver层:Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder;

  • 从Android Native层:Binder是创建Service Manager以及BpBinder/BBinder模型,搭建与binder驱动的桥梁;

  • 从Android Framework层:Binder是各种Manager(ActivityManager、WindowManager等)和相应xxxManagerService的桥梁;

  • 从Android APP层:Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的 Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。

[](()2.由来?

Android 系统是基于 Linux 内核的,Linux 已经提供了管道、消息队列、共享内存和 Socket 等 IPC 机制。那为什么 Android 还要提供 Binder 来实现 IPC 呢?主要是基于性能、稳定性和安全性几方面的原因。

  • 管道:任何进程都能通讯,但速度慢

  • 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。

  • 共享内存:能够容易控制容量,速度快,但要保持同步,比如写一个进程的时候,另一个进程要注意读写的问题,相当于线程中的线程安全。当然,共享内存同样可以作为线程通讯,不过没有这个必要,线程间本来就已经共享了同一个进程内的一块内存。

  • socket:本机进程之间可以利用socket通信,跨进程之间也可利用socket通信,通常RPC的实现最底层都是通过socket通信。socket通信是一种比较复杂的通信方式,通常客户端需要开启单独的监听线程来接受从服务端发过来的数据,客户端线程发送数据给服务端,如果需要等待服务端的响应,并通过监听线程接受数据,需要进行同步,是一件很麻烦的事情。socket通信速度也不快。

[](()3.Binder特性?

[](()3.1 性能?

[图片上传失败…(image-675747-1628086130715)]

  • 共享内存虽然无需拷贝,但控制复杂,难以使用。

  • Binder 只需要一次数据拷贝,性能上仅次于共享内存。

  • Socket 作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。

  • 消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。

[](()3.2 稳定性?
  • Binder 基于 C/S 架构,客户端(Client)有什么需求就丢给服务端(Server)去完成,架构清晰、职责明确又相互独立,自然稳定性更好。

  • 共享内存虽然无需拷贝,但是控制负责,难以使用。从稳定性的角度讲,Binder 机制是优于内存共享的。

[](()3.3 安全性?
  • 首先传统的 IPC 接收方无法获得对方可靠的进程用户ID/进程ID(UID/PID),从而无法鉴别对方身份。

  • Android 为每个安装好的 APP 分配了自己的 UID,故而进程的 UID 是鉴别进程身份的重要标志。传统的 IPC 只能由用户在数据包中填入 UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标识只有由 IPC 机制在内核中添加。其次传统的 IPC访问接入点是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。

  • 同时 Binder 既支持实名 Binder,又支持匿名 Binder,安全性高(Binder.getCallingUid())。

[](()3.4 结论:

[图片上传失败…(image-a27659-1628086130715)]

[](()三、Linux下IPC原理


[图片上传失败…(image-7a3593-1628086130715)]

[](()1.进程隔离

  • 进程与进程间内存是不共享的。两个进程就像两个平行的世界,A 进程没法直接访问 B 进程的数据,这就是进程隔离的通俗解释。

  • A 进程和 B 进程之间要进行数据交互就得采用特殊的通信机制:进程间通信(IPC)。

[](()2.用户空间与内核空间

  • 每个Android的进程,只能运行在自己进程所拥有的虚拟地址空间。对应一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间,当然内核空间的大小是可以通过参数配置调整的。对于用户空间,不同进程之间彼此是不能共享的,而内核空间却是可共享的。

  • 简单的说就是,内核空间(Kernel)是系统内核运行的空间,用户空间(User Space)是用户程序运行的空间。为了保证安全性,它们之间是隔离的。

[](()3.用户态与内核态

  • 虽然从逻辑上抽离出用户空间和内核空间;但是不可避免的的是,总有那么一些用户空间需要访问内核的资源;比如应用程序访问文件,网络是很常见的事情,怎么办呢?

  • 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(内核态)此时处理器处于特权级最高的(0级)内核代码中执行。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。处理器在特权等级高的时候才能执行那些特权CPU指令。

  • 系统调用主要通过如下两个函数来实现:

copy_from_user() //将数据从用户空间拷贝到内核空间

copy_to_user() //将数据从内核空间拷贝到用户空间

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值