Android Binder小结

这篇具有很好参考价值的文章主要介绍了Android Binder小结。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Binder小结

什么是Binder

  • Binder是Android中一种跨进程通信方式,Binder也是一个虚拟设备,对于客户端来说Bidner是一个可以跨进程通信的一个类

为什么Android要使用Binder进程间通信?

  • Android底层是Linux,但是Linux已有的跨进程通信方式都不能满足Android移动设备的需求,在Android中跨进程通信方式,要求是CS的一对多的架构、需要保证安全,并且效率高;在传统Linux跨进程通信方式中,Socket是CS架构,但是它不够安全、而且需要两次从用户空间和内核空间之间的拷贝;管道它比较安全,但是它只适合1对1,并且也需要两次拷贝;共享内存效率很高,1次拷贝都不需要,支持多对多,但是它不安全;还有其他像信号量、文件、消息等通信方式都无法完全满足Android移动设备的需求,所以Google工程师就开发了Binder作为Android中主要的通信方式,它属于CS架构,支持1对多,在安全性上通过uid、pid进行鉴权,效率上只需要1次拷贝就可以了

Binder实现原理

Binder模型主要包含这么几个角色:客户端Client、服务端Service、ServiceManager、Binder驱动;

  • Binder驱动是实现进程间通信的核心,它的核心原理在于使用了mmap内存映射技术,在内核空间中,将内核数据缓冲区的一块内存和内核中数据接收缓冲区进行了内存映射,然后数据接收缓冲区又跟用户空间中接收数据方所在进程有内存映射关系,所以当数据发送方所在进程发送数据时,会先将数据序列化后拷贝到内核数据缓冲区,由于内核数据缓冲区和数据接收缓冲区以及接收方用户进程内存映射,所以相当于直接将数据发送到了数据接收方所在进程;它之所以高效的原因就是因为使用了内存映射技术,减少了从内核空间拷贝到数据接收方所在的进程的过程

  • ServiceManager主要用于管理AMS\PMS等系统服务对应的Binder;当客户端需要使用系统服务的时,通过ServiceManager拿到对应系统服务的Binder代理类,比如ActivityManager\WIndowManager;这些代理类内部会持有系统服务器对应的Binder,通过跨进程方式实现方法的调用;

    • ServiceManager是在系统启动时init进程中启动的,同时启动的还有Zygote进程,Zygote进程又会创建SystemServer进程,SystemServer进程又会去启动AMS、PMS这些系统服务,然后这些系统服务又会以Binder形式注册到ServiceManager中,ServiceManager会在Binder驱动红黑树中添加相应的节点,保存相应的信息

    • ServiceManager在native层启动时,会打开Binder驱动,将自身作为服务注册到Binder句柄中(句柄号为0),然后开启binder循环接收客户端发过来的请求,处理系统服务器的注册、查找等

  • 为了简化客户端和服务端之间使用Binder跨进程通信的过程,Android提供了AIDL(全称是Android Interface define language);

    • 在aidl文件中定义服务端要提供的方法,编译时会使用aidl命令将我们定义的接口生成一个java接口类;这个接口类继承自IInterface接口;里面主要有两个内部类Stub和Proxy代理类;

    • 其中Stub类是继承自Binder并实现了我们定义的接口;其中有个onTransact方法以及用户定义的方法,在onTransact这个方法中会根据传递进来的参数,决定调用服务端哪个方法,并将结果进行Pacel序列化后返回,这个Stub类需要服务端在onBind方法中实现并作为Binder返回给客户端

    • 另一个是Proxy代理类,当客户端拿到服务端返回的Binder对象时,需要将改Binder对象转换成这个Proxy代理对象,这个代理类实现了用户定义的接口,并代理服务端的Binder对象进行远程调用,当客户端通过这个代理对象调用服务端某个方法时,会将要调用的方法名、方法参数序列化后,通过Binder的transact方法发送出去

    • 接着底层会通过BpBinder将数据转发到内核层的Bidner驱动,再通过内存映射直接发送到服务端所在进程,接着BbBinder接收到数据后会调用服务端Stub类里的onTransact方法,服务端这边再根据参数调用相应的方法并返回结果

Bundle传递数据为什么需要序列化?

因为Bundle传递数据,大多数是用于跨进程通信,进程之间内存空间是相互隔离的,无法直接访问,只有通过序列化之后,通过从用户空间拷贝到系统内核,再从系统内核拷贝到用户空间,才可以在另一个进程中通过反序列化后接收到

Binder线程池

在进程创建的时候,ProcessState里会为当前进程打开Binder驱动,通过mmap创建Binder数据接收缓存区,以及创建Binder线程池并开启主线程,默认最大是15个,Binder线程池中线程分为3类:主线程、普通线程、将当前线程加入到线程池的线程;

  • App中有多少Binder线程,是固定的吗?

    • app启动时在创建进程时默认会创建一个Binder主线程在运行,如果App中定义个其他服务在独立进程中,每个进程都至少会启动一个Binder主线程,后面根据跨进程通信请求次数,Binder会自动调成线程个数

    • 最大的Binder线程也不是固定的,在ProcessState类中定义的默认最大线程个数是15个,这15个(不包括主Binder线程和将当前线程加入到Binder线程池中的),这个最大线程个数是可以修改的,比如SystemServer中就将线程池线程最大个数改成了31个

用户空间和内核空间区别?

用户空间是指app代码运行所在空间,内核空间是指系统代码、驱动、内核等运行所在的空间,之所以要划分用户空间和内核空间,是为了让app的代码和系统代码互相隔离开来,如果说没有划分,那么app代码和系统代码就都在一个进程里了,当app崩溃了,系统也会跟着奔溃,而且不同app进程之间也没办法公用系统代码,划分了之后,系统代码在内核空间,可以跟所有app公用,并且app崩溃不会导致内核崩溃,保证系统的安全

什么是物理地址和虚拟地址?

物理地址就是内存条的真实地址,虚拟地址是MMU内存管理单元出来之后才有的,虚拟地址是给cpu用的,cpu不能通过虚拟地址直接访问内存,需要通过MMU转换后才能访问到真实的物理内存;

最早期的计算机cpu是可以直接访问内存真实物理地址的,当时的软件都很小,可能只有几kb大小,可以将软件直接加载进内存运行,但是后面软件越做越大,如果直接全部代码加载到内存就会导致内存很快不够用,为了解决这个问题就引入了MMU对物理内存进行管理,CPU不能直接访问物理内存,需要访问物理内存时需要经过MMU将虚拟地址转换成物理地址才行;执行的代码也只加载当前活跃的代码到内存中,执行完后再从磁盘告诉缓冲中读取,

Binder最大传输数据是多少?为什么?

  • 对于普通app来说是1M-8k,因为在创建进程的时候,ProcessState会在app用户空间和内核之间会通过mmap开辟一块空间进行内存映射,这块空间的大小就是1M-8k,进程之间传递数据都是通过这块内存来完成的,所以普通app最大限制是1M-8k

  • 但是我们也可以在jni开发中手动打开binder驱动,然后调用mmap方法定义一个超过1M-8k大小的内存映射空间用于进程之间传递数据,但是也不能是无限大的,因为在mmap方法中限制最大只能开辟4M的内存映射空间大小;而且不建议这么做,因为Binder设计的最初目的并不是为了跨进程传递大数据,而只是用于通信用的,如果要传递大数据,完全可以通过文件、Socket、共享内存等其他方式传递;如果强制重新开启Binder可能会对已有Binder驱动造成影响,从而影响app正常与系统服务的交互

  • 之所以是1M-8K而不是1M或者其他,是因为MMU内存管理单元从磁盘加载活跃代码时,为了避免频繁的IO,所以规定每次从磁盘至少读取1页的数据,1页就是4k数据大小,所以大小指定是4k的整数倍

  • 实际使用过程中往往可传递的数据小于1M-8k,这是因为Binder线程中可能有多个线程(最大15个)正在跨进程通信,多个线程之间是共用这1M-8k大小的;而且在跨进程过程中,往往除了用户要传递的数据,还需要携带包括进程信息、目标进程信息、要调用的方法等等信息在里面,所以实际可能的空间往往更小

简单讲讲mmap原理?Binder如何做到1次拷贝?

Binder会在内核空间开辟两块内存,一块用于接收从发送方进程传递过来的数据,一块用于与接收方进程通过mmap进行内存映射,这几块内存空间之间都相互映射,当数据通过copy_from_user拷贝到内核缓冲区时,因为内存映射关系,接收方进程可以直接读取到这部分数据,从而省去了copy_to_user将数据从内核拷贝到接收方进程这一步,从而实现1次拷贝

内存中的1页是什么,你怎么理解的?

1页指的是硬盘数据加载到内存时,一次读取的数据数量是4k,这是为了避免频繁的进行io导致的性能问题

AIDL生成的java类结构?

生成的接口类包含了我们在aidl中定义的方法,继承自IInterface,里面有两个内部类分别是Proxy和Stub,他们都实现了我们定义的接口;

  • 其中Stub类继承自Binder,内部有个onTransact方法,当跨进程远程调用服务端方法的时候,这个方法会被调用,在这个方法里会判断要请求的是哪个方法,然后调用服务端中这个Stub类的实现类中的方法;并将要返回的结果写入Parcel对象中

  • 而Proxy代理类是用于代理Binder对象进行跨进程访问,当调用代理类的方法时,内部会先将要请求的参数写入Parcel对象中,然后调用Binder的transact方法进行远程调用并返回结果

  • 当调用Binder的transact方法后,底层会通过BpBinder封装数据后转发远程调用请求,然后将数据拷贝到内核层,通过Binder驱动转发给服务端,服务端进程那边会通过BbBinder对数据进行解析,最终调用服务端Stub实现类里的onTransact方法

BindService启动Service与Binder服务实体的流程?

  • 客户端调用bindService方法后,会跨进程调用AMS方法去查找要启动服务的信息,判断对应的服务所在进程是否已经启动,如果还没有则先通知Zygote启动进程

  • 进程启动后会检查对应的Service是否已经创建,如果没有的话会通知ActivityThread先创建服务,创建完了之后会调用它的生命周期方法onCreate和onBind,在onBind方法中服务端会实现Stub类,这个Stub类继承自Binder

  • 然后Service所在进程会将Binder对象返回给AMS,ANS则会回调客户端的ServiceConnection接口的onServiceConnected方法,并把服务端onBind方法返回的Binder对象返回给客户端

  • 客户端拿到Binder对象后调用asInterface方法,这个方法里会根据是否跟服务端在一个进程中,来决定是返回服务端接口本身,还是返回支持跨进程通信的代理类Proxy

  • 接着客户端就可以直接调用Service提供的方法了

Binder如何找到目标进程的?

binder服务会事先在Binder驱动的红黑树中注册结点,当跨进程通信时Binder驱动会先从红黑树中查找目标Binder所在结点,从结点中获取进程、线程信息,然后去唤醒目标进程、线程

Binder严格意义上拷贝几次?

拷贝两次,在从用户空间拷贝到内核空间的时候,调用了两次copy_from_user方法,一次用于拷贝传递的方法和参数等信息、另一次拷贝进程、线程等附加信息;之所以两次而不是一次,可能是考虑到如果第一次拷贝失败时,就可以直接return,而不用进行第二次拷贝了,节约了拷贝的时间

Binder中的红黑树,为什么会有两棵binder_ref红黑树

一个是用于通过句柄查找,一个是用于通过结点查找,提高查找效率

系统服务与bindService等启动的服务的区别

系统服务的注册、和查找是通过ServiceManager完成的,而bindService则主要是通过AMS来完成的

Binder线程、Binder主线程、Client请求线程的概念与区别

在进程创建的时候,process_state类中会创建Binder线程池,创建Binder线程池所在线程叫做Binder主线程,它会监听客户端发过来的Binder的请求,然后为会客户端分配Binder线程,Binder线程是通过线程池创建的;客户端请求线程就是客户端发起Binder请求所在线程

为什么内核有内核缓存区还要有个数据接收缓存区?

因为内核缓冲区是一直就存在的,以往的跨进程通信就是先从发送方拷贝到内核缓存区,然后再拷贝到接收方,所以需要两次拷贝,Binder的出现创建了一块数据接收缓存区,通过mmap将接收方和系统内核缓存区连接起来,从而减少了一次拷贝文章来源地址https://www.toymoban.com/news/detail-402376.html

到了这里,关于Android Binder小结的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 进阶——Binder IPC之Binder IPC架构及原理概述(九)

    前面几篇文章,为我们学习Binder IPC通信机制提供了扎实的理论基础,接下来将正式进入Binder IPC通信架构及原理的解读。 Binder 是基于 C/S 架构的,由一系列的组件组成,包括 Client进程、Server进程、Service Manager进程、Binder 驱动。其中 Client进程、Server进程、Service Manager进程运行

    2023年04月09日
    浏览(31)
  • Android 基础技术——Binder 机制

    笔者希望做一个系列,整理 Android 基础技术,本章是关于Binder 机制 什么是Binder 机制:Binder 是一种进程间通信机制 驱动:Binder 是一个虚拟物理设备驱动 应用层:Binder 是一个能发起通信的 Java 类 为什么要使用Binder 图解析: 性能上:  binder小于共享内存 优于其他ipc 共

    2024年02月19日
    浏览(24)
  • 浅谈 Android Binder 监控方案

    在 Android 应用开发中,Binder 可以说是使用最为普遍的 IPC 机制了。我们考虑监控 Binder 这一 IPC 机制,一般是出于以下两个目的: 卡顿优化:IPC 流程完整链路较长,且依赖于其他进程,耗时不可控,而 Binder 调用本身通常又是以 RPC 形式对外提供能力的,使得我们在使用时更容

    2024年02月11日
    浏览(61)
  • [Android 13]Binder系列--获取服务

    获取服务 hongxi.zhu 2023-7-8 以 SurfaceFlinger 进程中获取 InputFlinger 服务为例 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp 获取到SM的代理对象之前的文章已经分析过,请参考前面的:Binder系列–获取ServiceManager BpServiceManager::getService remote()从前面可知是SM的BpBinder对象,获取到SM的

    2024年02月13日
    浏览(33)
  • Android 面试笔记整理-Binder机制

    作者:浪人笔记 面试可能会问到的问题 从IPC的方式问到Binder的优势 为什么zygote跟其他服务进程的通讯不使用Binder Binder线程池和Binder机制 等等这些问题都是基于你对Binder的理解还有对其他IPC通讯的理解 IPC方式有多少种 传统的IPC方式有Socket、共享内存、管道、信号量等 安卓

    2024年02月12日
    浏览(27)
  • [DEMO] Android Binder 的使用

    The Android binderfs Filesystem — The Linux Kernel documentation Android Binder 是一种 IPC 机制,IPC 键值/标识 是一个字符串,收发双方通过 键值/标识 建立通讯路径。 Binder 是通过模板类实现的,因此使用起来并不是那么简明通俗,如果没有demo可以参考的话是需要琢磨好一阵子。 class IInt

    2024年02月13日
    浏览(23)
  • Android Framework——Binder 监控方案

    作者:低性能JsonCodec 在 Android 应用开发中,Binder 可以说是使用最为普遍的 IPC 机制了。我们考虑监控 Binder 这一 IPC 机制,一般是出于以下两个目的: 卡顿优化:IPC 流程完整链路较长,且依赖于其他进程,耗时不可控,而 Binder 调用本身通常又是以 RPC 形式对外提供能力的,

    2024年02月04日
    浏览(24)
  • Android Binder通信原理(一):简介

    源码基于: Android R 在Linux 系统中现有的进程间通信(IPC)方式: 管道(PIPE): 在创建时分配一个page大小的内存,缓存区大小比较有限; 命名管道(FIFO): 考虑 PIPE_BUF 和原子操作; 消息队列: 信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信; 共享内存:  无须

    2024年02月10日
    浏览(24)
  • Android IPC Binder机制学习(一)

    一、多进程系统设计及意义 Android系统分为5层,不过Android一般岗位只关注上三层就够用了即:应用层、framework层、native层。 Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。 Android中不同的应用属于不同的进程中 Android应用和系统服务运行在不同的进

    2023年04月09日
    浏览(29)
  • Android 13(T) - binder阅读开篇

    原本计划用一个系列来记录自己学习Android Media框架的心得感受,但是刚刚起步就碰到了问题,由于Media框架中用了许多服务(binder service),而且我不太熟悉binder的用法,所以看代码的过程中心里总有些忐忑,害怕遇到binder,这对我对框架结构的理解学习是十分不利的。 bin

    2024年02月11日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包