Binder总结篇1-Binder原理

Binder总结篇1-Binder原理

需要学会Binder的基本使用和原理,需要的知识点有:

  1. Linux进程和空间的概念

  2. 虚拟地址概念

  3. 常用IPC,他们的基本流程和Binder的区别

  4. C/S架构基本思路,也就是Binder驱动,ServerManager,Client和Server这四个概念。

  5. AIDL以及支持的数据类型,包括Parcelable等,以及编写

  6. Service(Android的四大组件之一),Binder等几个具体的java类使用。

以下是自己的一些Binder学习总结,如有侵权请联系删除。

Linux的进程和空间的概念

在Linux系统中,进程是分配给应用程序运行的最小描述,即一个应用程序最少有一个进程,而一个进程之间又最少有一个线程,进程给应用程序分配内存空间。

空间:在Linux中,为了保持系统的稳定性,分为内核空间和用户空间,内核空间的权限最高,用户空间的权限最低。比如读写文件,网络请求就是在内核空间中进行的。

在Linux中,存在着进程隔离,也就是进程A无法直接访问进程B的数据,他们之间各自具有独立的内存。假如他们需要进行通信,就必须通过IPC来实现,主要是通过两个方法:copy_from_usercopy_to_user

虚拟地址

在给应用程序分配内存的时候,对于应用程序来说,他是一片连续的内存空间,但是实际上,这些内存空间映射到具体的物理内存中是碎片化的不连续的,这个在应用程序看来是连续的空间就是通过虚拟地址实现的。通过虚拟地址,让应用程序看似拥有连续的内存空间,从而映射到具体的物理内存中。

比如,在32位系统中,可以寻址的空间长度是2的32次方,也就是4GB。

传统IPC

包括:

  1. 共享内存

  2. 消息管道

  3. Socket

  4. 信号量

这些是常用的IPC方法,一般而言,他们会经历两次的数据copy,共享内存除外。

第一次是发送方将数据通过copy_from_user拷贝到内核空间中,这是第一次。然后,接收方在自己的内存空间中,分配缓存区,通过copy_to_user方法把内核空间的数据复制到自己进行读取。

如下图:

对于Android系统而言,上面的几种方式都不太适合,首先对于两次的数据拷贝,存在的问题是:

  1. copy次数多耗费时间

  2. 接收方不知道需要分配多大的内存接受数据,或者是需要提前通知接受方分配而耗费时间。

对于共享内存,虽然它无需copy但是较为难以控制,安全性方面较差。

那么Binder在这方面具有什么优势呢?

  1. Binder是只需要一次数据copy,仅低于共享内存。

  2. 他基于C/S架构,职责分离又相互独立,稳定性更好。

  3. 在安全性方面,传统的IPC接收方无法获取对方可靠的进程PId,从而无法鉴别对方身份。但是在Android中,他会为每一个安装好的App分配一个自己的UID,从而做到可以鉴别身份。

所以Binder是Android系统进行IPC采用的手段。那么Binder为什么只是可以一次数据拷贝就行了呢?

这个就是利用虚拟内存了。Binder借助内存映射,在内核空间和接收方的用户空间的数据缓存区做了一层内存映射。也就是说,在发送方将数据拷贝到内存空间的时候,内核空间的这部分地址同时也会被映射到接收方的内存缓存中,这样子,就少了一次从内和空间拷贝到用户空间。

如下图:

Binder 的通信原理

在Binder中,有四个概念,Binder驱动,ServerManager,Client以及Server,这四个部分组成了BinderC/S架构。

他跟一次网络请求很相似:Client通过域名发起请求,通过DNS域名解析器解析具体的ip地址,然后再通过路由转发到具体的Server,再然后Server将请求结果通过路由转发回Client。

在Binder的IPC中,有如下几个部分:

  1. Binder驱动

Binder驱动是一种虚拟的字符设备,注册在/dev/bindr中,其中定义了一套Binder通信协议,负责建立进程间Binder通信,提供了数据包在进程之间传递的底层支持。

他的角色类似路由,他是提供进程间通信的底层支持。负责将Client端的请求转发到Server,并将Server的数据返回给Client。

2 ServerManager

他的作用类似DNS服务器,负责将Client请求的Server的Binder描述转化为具体的Server地址,以便Binder驱动将Client的请求转达到Server。当Server需要提供服务的时候,他必须先向ServerManager注册,这样子,ServerManager中,就存有一份类似key-value的数据,保存了一份Server的Binder字符名称和Binder引用的映射以便Client可以找到。

  1. Client

Client的作用是发起请求,通过Binder向ServerManager发起请求获取Server的具体地址,然后交由Binder驱动转发。

  1. Server

Server假如需要对外提供服务,他就需要先将自己注册到ServerManager中,以便被解析出来。Server在响应请求之后,就将数据通过Binder驱动再次将数据传递会Client。

这就是一次完整的IPC调用。

还有一个问题就是ServerManager的产生,因为Client/Server都是需要通过Binder与ServerManager进行通信的,那么这个ServerManager是如何产生的呢?

  1. 在Android系统启动之后,会创建一个名词为servermanager的进程,可以查看ZygoteInit文件,在里面的main方法中,调用ZygoteforkSystemServer产生。它通过一个约定的命令BINDERSERVER_MGR向Binder驱动注册,申请成为ServerManager。Binder驱动会自动为ServerManager创建一个Binder实体

  2. 这个Binder实体的引用在所有的Client中都是0,也就是说各个Client通过0这个引用就可以与ServerManager进行通信。

Binder的代理机制

上面是我们的IPC过程,在这个过程中,Client需要获取到Server端的Binder引用,那么这个引用是真正的Server引用吗,他是如何实现的呢,A进程并无法直接获取B进程的对象。这个就是需要通过Binder的代理机制实现。

我们在Client端,向ServerManager获取具体的Server端的Binder引用的时候,会首先进过Binder驱动,Binder驱动它并不会把真正的Server的Bind人引用返回给Client端,而是返回一个代理的java对象,该对象具有跟Server端的Binder引用相同的方法签名,这个对象为ProxyObject,他具有跟Server的Binder实例一样的方法,只是这些方法并没有Server端的能力,这个ProxyObject的能力是可以通过Binder驱动,正在实现对Server的Binder进行调用,从而完成数据传递。

比如,当Binder驱动接受到Client进程的请求,就去ServerManager中查询,在ServerManager中查询到具体的Server具体之后,就创建一个Server端的Binder对象的ProxyObject,并且将该ProxyObject返回给Client 。然后Client就通过ProxyObject调用其中的方法,ProxyObject的方法再去调用Binder驱动,这个Binder驱动就去Server进程中,调用具体的Server进程的具体的Binder对象的方法,然后再通过Binder驱动返回数据给Client。

如下图

AIDL

上面我们大概梳理了Binder调用的整体流程,知道Binder的大概原理。在Android中,是通过AIDL这一描述性接口语言实现的。

什么是AIDL:Android 接口定义语言 (AIDL)

关于如何使用AIDL将在下一篇文章在做详细使用。

参考文章

关于Binder,作为应用开发者你需要知道的全部(同时也是本文的文章图片来源)

为什么Android要采用Binder作为IPC机制

Binder系列-开篇

Android 跨进程通信:图文详解Binder机制原理

写给 Android 应用工程师的 Binder 原理剖析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值