Binder机制深入理解

Binder机制深入理解

目录介绍
  • 01.Binder的背景介绍
    • 1.1 为何会有Binder
    • 1.2 什么是Binder
    • 1.3 常见进程通信
    • 1.4 为什么要用Binder
  • 02.Binder工作流程
    • 2.1 Binder运行机制
    • 2.2 工作流程介绍
    • 2.3 工作流程图
    • 2.4 举例说Binder通信
  • 03.Binder设计思想
    • 3.1 Binder设计流程
    • 3.2 Binder设计思考
  • 04.Binder源码流程
    • 4.1 Binder通信原理图
    • 4.2 Binder安全校验
00.先思考一些问题
  • 01.为什么会有Binder?不在同一个进程中的Activity和Service(比如把服务定义成一个独立进程)是如何通信的?
  • 02.Binder的设计思想是什么?多进程通信有哪些方式?为什么在Android系统中要是用Binder通信,有什么优缺点?
  • 03.进程通信有共享内存,管道,socket,消息队列。他们的原理大概都是什么样的?Binder中使用mmap是什么东西?
  • 04.既然有现有的IPC方式,为什么重新设计一套Binder机制呢。是否用Binder中mmap思想解决你的APP卡顿问题?
  • 05.Binder机制:ServiceManager什么时候注册的?这个是用来干嘛的?Binder内核所在的进程是如何找到到Server跟Client进行通信的?
01.Binder的背景介绍
1.1 为何会有Binder
  • 每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能运行在同一个进程中,也有可能运行在不同的进程中。
  • 作为一名Android开发,我们每天都在和Binder打交道,虽然可能有的时候不会注意到,譬如:
    • startActivity的时候,会获取AMS服务,调用AMS服务的startActivity方法
    • startActivity传递的对象为什么需要序列化
    • bindService为什么回调的是一个IBinder对象
    • 多进程应用,各个进程之间如何通信
    • AIDL的使用
  • 它们都和Binder有着莫切关系,当碰到上面的场景,或者一些疑难问题的时候,理解Binder机制是非常有必要的。这就是要介绍的Binder进程间通信机制。
1.2 什么是Binder
  • 1.直观来说,Binder是Android中的一个类,它继承了IBinder接口。
  • 2.从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在linux中没有
  • 3.从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁
  • 4.从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。
1.3 常见进程通信
  • 在传统的Linux上,我们还是有很多选择可以用来实现进程间通信
    • 如管道、SystemV、Socket、共享内存等。那么Android为什么不使用这些原有的技术,而是要使开发一种新的叫Binder的进程间通信机制呢?
  • 共享内存
    • 什么是共享内存:共享内存是进程间通信中最简单的方式之一,共享内存允许两个或更多进程访问同一块内存,当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。
    • image
    • 性能和安全分析:因为共享内存是访问同一块内存,所以数据不需要进行任何复制,是IPC几种方式中最快,性能最好的方式。由于能任意的访问和修改内存中的数据,如果有恶意程序去针对某个程序设计代码,很可能导致隐私泄漏或者程序崩溃,所以安全性较差。
  • 管道
    • 什么叫做管道:它具有固定的读端和写端,写进程通过写段向管道文件里写入数据,读进程通过读段从读进程中读出数据,构成一条数据传递的流水线。
    • image
    • 性能和安全分析:管道一次通信需要经历2次数据复制(进程A -> 管道文件,管道文件 -> 进程B)。管道的读写分阻塞和非阻塞,管道创建会分配一个缓冲区,而这个缓冲区是有限的,如果传输的数据大小超过缓冲区上限,或者在阻塞模式下没有安排好数据的读写,会出现阻塞的情况。
  • 消息队列
    • 什么叫消息队列:消息队列是存放在内核中的消息链表,每个消息队列由消息队列标识符表示。消息队列允许多个进程同时读写消息,发送方与接收方要约定好,消息体的数据类型与大小。
    • image
    • 性能和安全分析:消息队列克服了信号承载信息量少、管道只能承载无格式字节流等缺点,消息队列一次通信同样需要经历2次数据复制(进程A -> 消息队列,消息队列 -> 进程B)
  • Socket
    • 什么是Socket:Socket原本是为了网络设计的,但也可以通过本地回环地址 (127.0.0.1) 进行进程间通信。
    • image
    • 一个Socket会拥有两个缓冲区,一读一写,由于发送/接收消息需要将一个Socket缓冲区中的内容拷贝至另一个Socket缓冲区,所以Socket一次通信也是需要经历2次数据复制。
1.4 为什么要用Binder
  • 最简单的回答:
    • 性能:相比传统的Socket更高效;安全:安全性高,支持通信双方进行身份验证
  • 性能方面的优势
    • 在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。
    • Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。
  • 安全方面优势
    • 传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造。
    • 而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。
    • 还有一些好处,如实现面象对象的调用方式,在使用Binder时就和调用一个本地实例一样。
  • 为何说Binder相比传统的Socket性能更高效?
    • 跨进程通讯中,只有socket支持Client-Server的通信方式,但是socket作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。
    • 消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。
    • 共享内存虽然无需拷贝,但控制复杂,难以使用,而且相对来说特别不安全。
  • 为何说Binder相比传统IPC安全性更高?
    • 首先传统IPC的接收方无法获得对方进程可靠的UID和PID(用户ID进程ID),从而无法鉴别对方身份。Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。
    • 使用传统IPC只能由用户在数据包里填入UID和PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。其次传统IPC访问接入点是开放的,无法建立私有通道。
    • 比如命名管道的名称,systemV的键值,socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接。
    • 基于以上原因,Android需要建立一套新的IPC机制来满足系统对通信方式,传输性能和安全性的要求,这就是Binder。
    • Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。
02.Binder工作流程
2.1 Binder运行机制
  • Binder基于Client-Server通信模式,除了Client端和Server端,还有两角色一起合作完成进程间通信功能。
  • Binder通信的四个角色:
    • Client进程:使用服务的进程。
    • Server进程:提供服务的进程。
    • ServiceManager进程:ServiceManager的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。
    • Binder驱动:驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。
  • 接触这些概念可能会觉得难于理解,读者可以把四个角色和熟悉的互联网进行类比:
    • Server是服务器,Client是客户终端,ServiceManager是域名服务器(DNS),驱动是路由器。
    • 在这里插入图片描述
2.2 工作流程介绍
  • Binder的工作流程是怎样的?
    • 1客户端首先获取服务器端的代理对象。所谓的代理对象实际上就是在客户端建立一个服务端的“引用”,该代理对象具有服务端的功能,使其在客户端访问服务端的方法就像访问本地方法一样。
    • 2客户端通过调用服务器代理对象的方式向服务器端发送请求。
    • 3代理对象将用户请求通过Binder驱动发送到服务器进程。
    • 4服务器进程处理用户请求,并通过Binder驱动返回处理结果给客户端的服务器代理对象。
    • 5客户端收到服务端的返回结果。
2.3 工作流程图
  • binder工作流程图如下所示:
    • image
  • Binder主要能提供哪些功能?
    • 用驱动程序来推进进程间的通信。
    • 通过共享内存来提高性能。
    • 为进程请求分配每个进程的线程池。
    • 针对系统中的对象引入了引用计数和跨进程的对象引用映射。
    • 进程间同步调用。
2.4 举例说Binder通信
  • 我们知道应用进程与SystemServer进程属于两个不同的进程,进程之间需要通讯。举例子比如说:AMS通信
    • android系统采取了自身设计的Binder机制,这里的ActivityManagerProxy和ActivityManagerNative都是继承与IActivityManager的而SystemServer进程中的ActivityManagerService对象则继承与ActivityManagerNative。
  • 简单的表示:Binder接口 --> ActivityManagerNative/ActivityManagerProxy --> ActivityManagerService;
    • 这样ActivityManagerNative与ActivityManagerProxy相当于一个Binder的客户端
    • 而ActivityManagerService相当于Binder的服务端
    • 这样当ActivityManagerNative调用接口方法的时候底层通过Binder driver就会将请求数据与请求传递给server端,并在server端执行具体的接口逻辑。
    • 需要注意的是Binder机制是单向的,是异步的,也就是说只能通过client端向server端传递数据与请求而不同等待服务端的返回,也无法返回,
    • 那如果SystemServer进程想向应用进程传递数据怎么办?这时候就需要重新定义一个Binder请求以SystemServer为client端,以应用进程为server端,这样就是实现了两个进程之间的双向通讯。
03.Binder设计思想
3.1 Binder设计流程
  • Binder设计流程图
    • image
  • 通过图来说一下流程
    • Server进程向ServiceManager注册,告诉ServiceManager我是谁,我有什么,我能做什么。就好比徐同学(Server进程)有一台笔记本(computer对象),这台笔记本有个add方法。这时映射关系表就生成了。
    • Client进程向ServiceManager查询,我要调用Server进程的computer对象的add方法,可以看到这个过程经过Binder驱动,这时候Binder驱动就开始发挥他的作用了。当向ServiceManager查询完毕,是返回一个computer对象给Client进程吗?其实不然,Binder驱动将computer对象转换成了computerProxy对象,并转发给了Client进程,因此,Client进程拿到的并不是真实的computer对象,而是一个代理对象,即computerProxy对象。很容易理解这个computerProxy对象也是有add方法,(如果连add方法都没有,岂不是欺骗了Client?),但是这个add方法只是对参数进行一些包装而已。
    • 当Client进程调用add方法,这个消息发送给Binder驱动,这时驱动发现,原来是computerProxy,那么Client进程应该是需要调用computer对象的add方法的,这时驱动通知Server进程,调用你的computer对象的add方法,将结果给我。然后Server进程就将计算结果发送给驱动,驱动再转发给Client进程,这时Client进程还蒙在了鼓里,他以为自己调用的是真实的computer对象的add方法,其实他只是调用了代理而已。不过Client最终还是拿到了计算结果。
3.2 Binder设计思考
  • Binder设计思考
    • Service Manager是如何成为一个守护进程的?即Service Manager是如何告知Binder驱动程序它是Binder机制的上下文管理者。
    • Server和Client是如何获得Service Manager接口的?即defaultServiceManager接口是如何实现的。
    • Server是如何把自己的服务启动起来的?Service Manager在Server启动的过程中是如何为Server提供服务的?即IServiceManager::addService接口是如何实现的。
    • Service Manager是如何为Client提供服务的?即IServiceManager::getService接口是如何实现的。
3.4 Binder线程管理
  • Binder中是如何进行线程管理的?
    • 每个Binder的Server进程会创建很多线程来处理Binder请求,可以简单的理解为创建了一个Binder的线程池吧(虽然实际上并不完全是这样简单的线程管理方式),而真正管理这些线程并不是由这个Server端来管理的,而是由Binder驱动进行管理的。
    • 一个进程的Binder线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。理解这一点的话,你做进程间通信时处理并发问题就会有一个底,比如使用ContentProvider时(又一个使用Binder机制的组件),你就很清楚它的CRUD(创建、检索、更新和删除)方法只能同时有16个线程在跑。
  • 总结binder讲的是什么?
    • 通常意义上来说,Binder就是指Android的通信机制;
    • 对于服务端进程来说,Binder指的是Binder本地对象,对于客户端进程来说,Binder指的是Binder代理对象。
    • 对于传输过程来说,Binder是可以进行跨进程传递的对象;
04.Binder源码流程
4.1 Binder通信原理图
  • Binder底层使用到mmap
    • Binder是基于内存映射mmap设计实现的,通过这种方式,直接操作映射的这一部分内存,通过mmap,Binder通信时,只需要经历一次数据复制,从而获得更好的性能。
  • 一次Binder IPC通信的过程分为以下几个步骤:
    • 首先,Binder驱动在内核空间中开辟出一个数据接收缓冲区
    • 接着,在内核空间中开辟出一个内核缓冲区
    • 将内核缓冲区与数据接收缓冲区建立映射关系
    • 将数据接收缓冲区与接收进程的用户空间地址建立映射关系
    • 发送方进程通过copy_from_user将数据从用户空间复制到内核缓冲区
    • 由于内核缓冲区与数据接收缓冲区有映射关系,同时数据接收缓冲区与接收进程的用户空间地址有映射关系,所以在接收进程中可以直接获取到这段数据
  • 这样便完成了一次Binder IPC通信,它的原理如下图所示:
    • image
4.2 Binder安全校验
  • 下图展示Binder IPC架构的一个简单例子。
    • image
    • 每个通过Binder框架实现IBinder接口,允许被访问调用的对象都可被称作Binder对象。对Binder对象的调用在一个Binder事务处理(transaction)内部实现,其中包括一个对目标对象的引用、需执行方法的ID和一个数据缓冲区。
  • 如何保证Binder安全性
    • Binder驱动会将调用进程的ID(PID)和有效用户ID(EUID)自动添加到事务处理数据。被调用进程可以检查PID和EUID,然后基于内部实现逻辑来决定是否执行所请求的方法。
    • 因为PID和EUID是由内核填写的,所以调用者进程不能通过伪造身份标识来获取超出系统允许的权限。这是Android安全模型的核心之一,所有更高层次抽象,比如权限,均是建立在它之上。
    • 调用者的PID和EUID通过类android.os.Binder的getCallingPid()和getCallingUid()来访问,他们是Android公开API的一部分。

原文地址: Binder机制深入理解-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
千里马8年Android系统及应用开发经验,曾担任过美国unokiwi公司移动端技术总监兼架构师,对系统开发,性能优化,应用高级开发有深入的研究,Android开源定制ROM Lineage的贡献者之一,国内首家线下开辟培训Android Framework课程,拥有2年的Android系统培训经验。成为腾讯课堂专业负责android framework课程分享第一人,致力于提高国内android Framework水平Android Framework领域内是国内各大手机终端科技公司需要的人才,应用开发者都对Android系统充满着好奇,其中的binder是重中之重,都说无binderAndroidbinde是Android系统的任督二脉。课程水平循序渐进,由中级再到高级,满足各个层次水平的android开发者。1、灵活使用binder跨进程通信,在app端对它的任何api方法等使用自如2、可以单独分析android系统源码中任何binder部分,分析再也没有难度3、掌握binder驱动本质原理,及对应binder驱动怎么进行跨进程通信,及内存等拷贝方式数据等4、对binder从上层的java app端一直到最底层的内核binder驱动,都可以顺利理通5、针对系统开发过程中遇到的binder报错等分析方法,及binder bug案例学习6、针对面试官任何的binder问题都可以对答自如7、socket这种跨进程通信实战使用8、针对android源码中使用的socket源码轻松掌握9、android系统源码中最常见的socketpair中双向跨进程通信10、使用socket实现一个可以让app执行shell命令的程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值