Android应用开发之android机制之Binder机制解析
凌雪 2018-09-21 来源 :网络 阅读 537 评论 0

摘要:本文将带你了解Android应用开发之android机制之Binder机制解析,希望本文对大家学Android有所帮助。

本文将带你了解Android应用开发之android机制之Binder机制解析,希望本文对大家学Android有所帮助。


android机制之Binder机制解析,在学习Binder的过程中有很多迷惑和难度。而且app开发很少接触到这个。翻看了无数的帖子,3-4本PDF/书,都是上来就将驱动的binder,然后将c++,再将到java层。诚然这是合理的架构设计顺序。但是对于java开发人员就痛苦了。我习惯的是从用法->原理的理解过程。
      我建议android app开发人员,学习过程按照一层一层往下。在不熟悉下一层的时候没关系,就当它是黑盒,这也是面向对象的思想,抽象后的对象(比如ActivityManagerService,ServiceManager等)我们都可以当它为黑盒。
      根据我踩坑后得到的浅浅经验,建议纯app开发人员如此开始:
    第一步,AIDL
  阅读之前请结合自己实现AIDL和AIDL使用和原理,先从AIDL学起的使用,自己生成一个AIDL文件,分析AIDL自动生成的代码。
?1234package com.allan.service;interface   IManager { void callServer(String info);}
学完以后,大概能理解到android机制系列之一 AIDL实现原理这个层次。
    第一步,学到
    AIDL
  大类实现了IInterface,把方法添加了远程异常;
Stub继承Binder,主要初始化,asInterface转换接口,和处理回调onTransact();
    Proxy实现大类,将Ibinder封装成具体同名方法transcat()给底层传递数据。
    使用层面来讲,只要asInterface()后就是具体的接口可以正常使用了。
Service
  onBinder() return   IInterface回去binder对象,在自动代码中会attachInterface()保留该实体对象
Client
  onServiceConnected()   会返回IBinder对象(mRemote#1), Client拿到后,需要asInterface()->queryLocalInterface()转成我们需要的代理对象(不同进程)或实体对象(同进程)
通信过程
      同进程实体方法调用: 同一进程空间,直接调用;
      不同进程代理对象方法调用:
      client将调用方法,参数_data和返回结果_reply序列化,mRemote#1(注意是Ibinder)transact(code, _data, _reply, flag)到黑盒Binder机制里面去,挂起;
service收到黑盒Binder机制回调给Stub的onTransact(code, data, reply, flag)   , 将data读取出来执行,如果有返回值就填充reply,然后结束,唤醒client;
client唤醒后,如果有返回值,就将_reply反序列化,拿到结果。
    第一步,黑盒:
    ?123Binder.java是怎么运作的?context.bindService(intent, serviceConnection, flag)怎么个流程?这个serviceConnection给谁去运作和怎么回调的?
    第二步,bindService, onBind和onServiceConnected的过程
?继续当Binder.java提供的方法为黑盒。暂时我们知道transact, onTransact的用处就够。我们一般bindService会在Activity/service中绑定。我们先看2张类图。
   
      理解下为何会使用wrapper(装饰/包装)模式,继承父类,又传入父类。查看源码ContextWrapper相当于完全照抄了一遍一些跟应用相关的方法,并可以初始化或者重设mBase。设想如果我们采用继承方式来做会丢失如下2点优势。
      好处有2点,第一,扩展(目前来说没有扩展)但不能修改父类;第二,可以方便的替换掉Impl类,而不用影响ContextWrapper的子类。
   
    不懂不要紧,我们来稍微类比下AIDL:
      第一步中自动实现的AIDL的IManager整个大类,就相当于这里的IActivityManager,实现了IInterface;
  ActivityManagerNative相当于我们AIDL的Stub类,内部可以拿到ActivityManagerService实现的接口,实现了OnTract(),外加Proxy代理类;
    该类类图:
   
      所以,ActivityManagerNative.getDefault().xxx(),其实都是跨进程调用(如果它自己则不用)到ActivityManagerService的具体实现。而这里并没有超出我们学习AIDL相关的范畴。因此,暂时不深入研究Binder,我们目前只要知道transact()和onTransact()是谁调用,在哪里用的即可,而且我们已经掌握。
      好了,这个时候,我们已经追到AMS的bindService了:然后学习Android服务之bindService源码分析。
? 里面很多的LoadedApk,ActivityThread,ActivityManagerService,ActivityServices等跳来跳去,一时之间很难理清楚。模模糊糊我们有了一些概念,留着后续继续学习,这里留一个黑盒。因为Activity,Service的启动流程等等都会涉及到这里。参考:https://blog.csdn.net/zhangfei2018/article/details/46518615
第二步,学到:
   
      我自己画的这张图, 而且是真的理解了。注意进程的关系,和子类归属关系。虚线是跨进程,实线是父类方法或者成员变量的方法。
?123456789ContextImpl相当于Activity/Service的父类(本质上是包装过的); ActivityManagerNative其实是静态类,我们拿到的静态对象去bindService的时候,其实还是在client进程; ActivityThread是每一个应用程序都需要通过标准java的main()函数创建出来的, 并且每个Service都有一个ActivityThread的成员变量(即我们常说的主线程); ActivityManagerService是SystemServer进程里的,他也有一个标记为system的ActivityThread; 所以在这里面涉及到3个进程,client的activity/service bindService的地方, service提供IBinder的地方以及framework的AMS。那么, 可以大致看出ActivityManagerService维护了一个所有应用层服务的表,client启动的时候添加进去;当client通过binder绑定的时候, 从表中找到对应intent的service,将serviceConnection封装进去,返回Ibinder,最后又通过Binder转达到client。
    回来来看,我们是想了解Binder,但是事实上,Binder的用法在上述流程中并没有太多的变化。所以回头来,再次巩固下java层的Binder知识。
    一个接口实现类:实现 IInterface;如 IActivityManager, IServiceManager, 如AIDL文件,如;
    一个主类: 继承Binder; 如AIDL的Stub类,如ActivityManagerNative;
    一个代理类,一般是主类内部类:实现接口实现类:如AIDL Stub内的Proxy类,如ActivityManagerNative内的ActivityManagerProxy类;
    主类方法具体实现:真正的实现方法,如ActivityManagerNative的ActivityManagerService,如AIDL的我们在service中实现的Stub的实例;
    主类Binder驱动回调方法onTransact():将Binder调过来的指令调用上述具体实现,并返回;
Proxy类方法抽象实现:将同名方法,使用binder驱动transact()传递指令同步等待结果。
    至此,Java层的binder使用和阅读framework   java层,在多次折腾下,基本算是懂了个大概。
    第二步,留下的黑盒:
    Binder底层机制;
ActivityManagerService,ActivityThread,Activity启动过程,Service启动过程,Application启动过程…
第三步 Binder C++使用学习:
TODO
第四步 其他帖子的学习:
    只有到了这个阶段,再去看后面引用的几篇文章才有意义!, 否则App开发工程师,上来就是驱动,很吃力。
    引用贴说的好,学习顺序。目前我已经达到了3阶段水平了。对于app工程师,基本能够比较轻松的继续研究Activity启动流程,广播机制,ContentProvider机制等framework机制就够了。否则,Binder学1个月也不能完成。
    引用灰太狼一句话:我还会回来的。
   
     先学会熟练使用AIDL进行跨进程通信(简单来说就是远程Service) 看Android文档,Parcel, IBinder, Binder等涉及到跨进程通信的类 不依赖AIDL工具,手写远程Service完成跨进程通信 看《Binder设计与实现》 看老罗的博客或者书(书结构更清晰) 再看《Binder设计与实现》 学习Linux系统相关知识;自己看源码。
   
    背景知识:
    进程间是隔离的,进程间,虚拟地址空间,无法共享数据;所以需要IPC,性能上讲,相对较少,一次内存拷贝,其他的一般2次;共享内存不用拷贝,但是很复杂难以使用,也不利于安全;socket适合网络通信或者一些低速的通信;安全上讲,传统linux的IPC相对来说很少涉及UID/PID,一些权限管理不够安全;
Binder驱动,内核模块虚拟成一种硬件设备,操作不同进程的内存;
在阅读Binder的通信模型的时候,经常会被他们提到Binder驱动,ServiceManager,Server,Client四个角色。
   
     serviceManager进程向binder驱动申请成为0号管理者;
     其他Server向serviceManager注册;
Client通过serviceManager获取具体Server的proxy引用对象。
   
    这里的Server并不是我们平时使用的组件service(https://blog.csdn.net/sinat_26158619/article/details/51184927)。binder提供了实名server和匿名server,framework java层使用了匿名server的技术,实现了组件service,https://blog.csdn.net/zhangyongfeiyong/article/details/51953300,也可以自己去追相关的源码,可以看到bindService的时候,是通过activityManagerService查询到对应的intent的服务,最终拿到的service代理。
    所以理解这里的AIDL服务service和binder   server的区别。
    但是,不管怎么样,如果不是同一进程,拿到的代理引用对象,都会通过binder驱动代码完成跨进程通信。
title bindService时序图 client->client:   bindService:ContextWrapperclient->client:   bindService:ContextImplclient->client:   bindServiceCommon:ContextImplclient->ActivityManagerNative:   bindService:ActivityManagerNativeActivityManagerNative-->ActivityManagerService:   bindService:ActivityManagerServiceActivityManagerService->ActivityManagerService:   bindServiceLocked:ActivityServicesActivityManagerService-->AcitivityThread:   scheduleCreateService-->handleCreateServiceActivityManagerService-->AcitivityThread:   scheduleBindService-->handleBindServiceAcitivityThread->Service:onBind()   AcitivityThread->Service:onBind()   AcitivityThread-->ActivityManagerService:publishService()ActivityManagerService->ActivityManagerService:publishServiceLocked:ActivityServicesActivityManagerService->ActivityManagerService:doConnect   handler:LoadedApkActivityManagerService-->client: onServiceConnected()    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注移动开发之Android频道!

本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程