当前位置: 首页 > news >正文

网站建设与管理代码建设网站需要多少钱济南兴田德润o地址

网站建设与管理代码,建设网站需要多少钱济南兴田德润o地址,网站备案好不好,网站建设需要那些人才转载#xff1a;http://weishu.me/2016/01/12/binder-index-for-newer/ Binder学习指南 发表于 2016-01-12 | 92条评论 | 34011次阅读毫不夸张地说#xff0c;Binder是Android系统中最重要的特性之一#xff1b;正如其名“粘合剂”所喻#xff0c;它是系统间各个组件…转载http://weishu.me/2016/01/12/binder-index-for-newer/ Binder学习指南 发表于 2016-01-12   |   92条评论   |   34011次阅读毫不夸张地说Binder是Android系统中最重要的特性之一正如其名“粘合剂”所喻它是系统间各个组件的桥梁Android系统的开放式设计也很大程度上得益于这种及其方便的跨进程通信机制。 理解Binder对于理解整个Android系统有着非常重要的作用Android系统的四大组件AMSPMS等系统服务无一不与Binder挂钩如果对Binder不甚了解那么就很难了解这些系统机制从而仅仅浮游与表面不懂Binder你都不好意思说自己会Android开发要深入AndroidBinder是必须迈出的一步。 现在网上有不少资料介绍Binder个人觉得最好的两篇如下 Binder设计与实现Android进程间通信IPC机制Binder简要介绍和学习计划系列 其中, 《Binder设计与实现》以一种宏观的角度解释了Android系统中的Binder机制文章如行云流水如果对于Binder有一定的了解再来看着篇文章有一种打通任督二脉的感觉每看一次理解就深一层。老罗的系列文章则从系统源码角度深入分析了Binder的实现细节具有很大的参考意义每当对于Binder细节有疑惑看一看他的书就迎刃而解。 但是遗憾的是Binder机制终究不是三言两语就能解释清楚的一上来就扒出源码很可能深陷细节无法自拔老罗的文章那不是一般的长如果看不懂强行看很容易睡着勉强看完还是云里雾里相反如果直接大谈特谈Binder的设计那么完全就是不知所云因此上述两篇文章对于初学者并不友好本文不会深入源码细节也不会对于Binder的设计高谈阔论重点如下 一些Linux的预备知识Binder到底是什么Binder机制是如何跨进程的一次Binder通信的基本流程是什么样深入理解Java层的Binder 读完本文你应该对于Java层的AIDL了如指掌对于Binder也会有一个大体上的认识再深入学习就得靠自己了本人推荐的Binder学习路径如下 先学会熟练使用AIDL进行跨进程通信简单来说就是远程Service看完本文看Android文档Parcel, IBinder, Binder等涉及到跨进程通信的类不依赖AIDL工具手写远程Service完成跨进程通信看《Binder设计与实现》看老罗的博客或者书书结构更清晰再看《Binder设计与实现》学习Linux系统相关知识自己看源码。 背景知识 为了理解Binder我们先澄清一些概念。为什么需要跨进程通信IPC怎么做到跨进程通信为什么是Binder 由于Android系统基于Linux内核因此有必要了解相关知识。 进程隔离 进程隔离是为保护操作系统中进程互不干扰而设计的一组不同硬件和软件的技术。这个技术是为了避免进程A写入进程B的情况发生。 进程的隔离实现使用了虚拟地址空间。进程A的虚拟地址和进程B的虚拟地址不同这样就防止进程A将数据信息写入进程B。 以上来自维基百科操作系统的不同进程之间数据不共享对于每个进程来说它都天真地以为自己独享了整个系统完全不知道其他进程的存在(有关虚拟地址请自行查阅因此一个进程需要与另外一个进程通信需要某种系统机制才能完成。 用户空间/内核空间 详细解释可以参考Kernel Space Definition简单理解如下 Linux Kernel是操作系统的核心独立于普通的应用程序可以访问受保护的内存空间也有访问底层硬件设备的所有权限。 对于Kernel这么一个高安全级别的东西显然是不容许其它的应用程序随便调用或访问的所以需要对Kernel提供一定的保护机制这个保护机制用来告诉那些应用程序你只可以访问某些许可的资源不许可的资源是拒绝被访问的于是就把Kernel和上层的应用程序抽像的隔离开分别称之为Kernel Space和User Space。 系统调用/内核态/用户态 虽然从逻辑上抽离出用户空间和内核空间但是不可避免的的是总有那么一些用户空间需要访问内核的资源比如应用程序访问文件网络是很常见的事情怎么办呢 Kernel space can be accessed by user processes only through the use of system calls. 用户空间访问内核空间的唯一方式就是系统调用通过这个统一入口接口所有的资源访问都是在内核的控制下执行以免导致对用户程序对系统资源的越权访问从而保障了系统的安全和稳定。用户软件良莠不齐要是它们乱搞把系统玩坏了怎么办因此对于某些特权操作必须交给安全可靠的内核来执行。 当一个任务进程执行系统调用而陷入内核代码中执行时我们就称进程处于内核运行态或简称为内核态此时处理器处于特权级最高的0级内核代码中执行。当进程在执行用户自己的代码时则称其处于用户运行态用户态。即此时处理器在特权级最低的3级用户代码中运行。处理器在特权等级高的时候才能执行那些特权CPU指令。 内核模块/驱动 通过系统调用用户空间可以访问内核空间那么如果一个用户空间想与另外一个用户空间进行通信怎么办呢很自然想到的是让操作系统内核添加支持传统的Linux通信机制比如Socket管道等都是内核支持的但是Binder并不是Linux内核的一部分它是怎么做到访问内核空间的呢Linux的动态可加载内核模块Loadable Kernel ModuleLKM机制解决了这个问题模块是具有独立功能的程序它可以被单独编译但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。这样Android系统可以通过添加一个内核模块运行在内核空间用户进程之间的通过这个模块作为桥梁就可以完成通信了。 在Android系统中这个运行在内核空间的负责各个用户进程通过Binder通信的内核模块叫做Binder驱动; 驱动程序一般指的是设备驱动程序Device Driver是一种可以使计算机和设备通信的特殊程序。相当于硬件的接口操作系统只有通过这个接口才能控制硬件设备的工作 驱动就是操作硬件的接口为了支持Binder通信过程Binder使用了一种“硬件”因此这个模块被称之为驱动。 为什么使用Binder Android使用的Linux内核拥有着非常多的跨进程通信机制比如管道System VSocket等为什么还需要单独搞一个Binder出来呢主要有两点性能和安全。在移动设备上广泛地使用跨进程通信肯定对通信机制本身提出了严格的要求Binder相对出传统的Socket方式更加高效另外传统的进程通信方式对于通信双方的身份并没有做出严格的验证只有在上层协议上进行架设比如Socket通信ip地址是客户端手动填入的都可以进行伪造而Binder机制从协议本身就支持对通信双方做身份校检因而大大提升了安全性。这个也是Android权限模型的基础。 Binder通信模型 对于跨进程通信的双方我们姑且叫做Server进程简称ServerClient进程简称Client由于进程隔离的存在它们之间没办法通过简单的方式进行通信那么Binder机制是如何进行的呢 回想一下日常生活中我们通信的过程假设A和B要进行通信通信的媒介是打电话A是ClientB是ServerA要给B打电话必须知道B的号码这个号码怎么获取呢通信录. 这个通信录就是一张表内容大致是 1 2B - 12345676 C - 12334354先查阅通信录拿到B的号码才能进行通信否则怎么知道应该拨什么号码回想一下古老的电话机如果A要给B打电话必须先连接通话中心说明给我接通B的电话这时候通话中心帮他呼叫B连接建立就完成了通信。 另外光有电话和通信录是不可能完成通信的没有基站支持信息根本无法传达。 我们看到一次电话通信的过程除了通信的双方还有两个隐藏角色通信录和基站。Binder通信机制也是一样两个运行在用户空间的进程要完成通信必须借助内核的帮助这个运行在内核里面的程序叫做Binder驱动它的功能类似于基站通信录呢就是一个叫做ServiceManager的东西简称SM OKBinder的通信模型就是这么简单如下图 整个通信步骤如下 SM建立(建立通信录)首先有一个进程向驱动提出申请为SM驱动同意之后SM进程负责管理Service注意这里是Service而不是Server因为如果通信过程反过来的话那么原来的客户端Client也会成为服务端Server不过这时候通信录还是空的一个号码都没有。各个Server向SM注册(完善通信录)每个Server端进程启动之后向SM报告我是zhangsan, 要找我请返回0x1234(这个地址没有实际意义类比)其他Server进程依次如此这样SM就建立了一张表对应着各个Server的名字和地址就好比B与A见面了说存个我的号码吧以后找我拨打10086Client想要与Server通信首先询问SM请告诉我如何联系zhangsanSM收到后给他一个号码0x1234Client收到之后开心滴用这个号码拨通了Server的电话于是就开始通信了。 那么Binder驱动干什么去了呢这里Client与SM的通信以及Client与Server的通信都会经过驱动驱动在背后默默无闻但是做着最重要的工作。驱动是整个通信过程的核心因此完成跨进程通信的秘密全部隐藏在驱动里面这个我们稍后讨论。 OK上面就是整个Binder通信的基本模型做了一个简单的类比当然也有一些不恰当的地方(比如通信录现实中每个人都有一个但是SM整个系统只有一个基站也有很多个但是驱动只有一个但是整体上就是这样的我们看到其实整个通信模型非常简单。 Binder机制跨进程原理 上文给出了Binder的通信模型指出了通信过程的四个角色: Client, Server, SM, driver; 但是我们仍然不清楚Client到底是如何与Server完成通信的。 两个运行在用户空间的进程A和进程B如何完成通信呢内核可以访问A和B的所有数据所以最简单的方式是通过内核做中转假设进程A要给进程B发送数据那么就先把A的数据copy到内核空间然后把内核空间对应的数据copy到B就完成了用户空间要操作内核空间需要通过系统调用刚好这里就有两个系统调用copy_from_user, copy_to_user。 但是Binder机制并不是这么干的。讲这么一段是说明进程间通信并不是什么神秘的东西。那么Binder机制是如何实现跨进程通信的呢 Binder驱动为我们做了一切。 假设Client进程想要调用Server进程的object对象的一个方法add;对于这个跨进程通信过程我们来看看Binder机制是如何做的。 通信是一个广泛的概念只要一个进程能调用另外一个进程里面某对象的方法那么具体要完成什么通信内容就很容易了。 首先Server进程要向SM注册告诉自己是谁自己有什么能力在这个场景就是Server告诉SM它叫zhangsan它有一个object对象可以执行add 操作于是SM建立了一张表zhangsan这个名字对应进程Server; 然后Client向SM查询我需要联系一个名字叫做zhangsan的进程里面的object对象这时候关键来了进程之间通信的数据都会经过运行在内核空间里面的驱动驱动在数据流过的时候做了一点手脚它并不会给Client进程返回一个真正的object对象而是返回一个看起来跟object一模一样的代理对象objectProxy这个objectProxy也有一个add方法但是这个add方法没有Server进程里面object对象的add方法那个能力objectProxy的add只是一个傀儡它唯一做的事情就是把参数包装然后交给驱动。(这里我们简化了SM的流程见下文) 但是Client进程并不知道驱动返回给它的对象动过手脚毕竟伪装的太像了如假包换。Client开开心心地拿着objectProxy对象然后调用add方法我们说过这个add什么也不做直接把参数做一些包装然后直接转发给Binder驱动。 驱动收到这个消息发现是这个objectProxy一查表就明白了我之前用objectProxy替换了object发送给Client了它真正应该要访问的是object对象的add方法于是Binder驱动通知Server进程调用你的object对象的add方法然后把结果发给我Sever进程收到这个消息照做之后将结果返回驱动驱动然后把结果返回给Client进程于是整个过程就完成了。 由于驱动返回的objectProxy与Server进程里面原始的object是如此相似给人感觉好像是直接把Server进程里面的对象object传递到了Client进程因此我们可以说Binder对象是可以进行跨进程传递的对象 但事实上我们知道Binder跨进程传输并不是真的把一个对象传输到了另外一个进程传输过程好像是Binder跨进程穿越的时候它在一个进程留下了一个真身在另外一个进程幻化出一个影子这个影子可以很多个Client进程的操作其实是对于影子的操作影子利用Binder驱动最终让真身完成操作。 理解这一点非常重要务必仔细体会。另外Android系统实现这种机制使用的是代理模式, 对于Binder的访问如果是在同一个进程不需要跨进程那么直接返回原始的Binder实体如果在不同进程那么就给他一个代理对象影子我们在系统源码以及AIDL的生成代码里面可以看到很多这种实现。 另外我们为了简化整个流程隐藏了SM这一部分驱动进行的操作实际上由于SM与Server通常不在一个进程Server进程向SM注册的过程也是跨进程通信驱动也会对这个过程进行暗箱操作SM中存在的Server端的对象实际上也是代理对象后面Client向SM查询的时候驱动会给Client返回另外一个代理对象。Sever进程的本地对象仅有一个其他进程所拥有的全部都是它的代理。 一句话总结就是Client进程只不过是持有了Server端的代理代理对象协助驱动完成了跨进程通信。 Binder到底是什么 我们经常提到Binder那么Binder到底是什么呢 Binder的设计采用了面向对象的思想在Binder通信模型的四个角色里面他们的代表都是“Binder”这样对于Binder通信的使用者而言Server里面的Binder和Client里面的Binder没有什么不同一个Binder对象就代表了所有它不用关心实现的细节甚至不用关心驱动以及SM的存在这就是抽象。 通常意义下Binder指的是一种通信机制我们说AIDL使用Binder进行通信指的就是Binder这种IPC机制。对于Server进程来说Binder指的是Binder本地对象对于Client来说Binder指的是Binder代理对象它只是Binder本地对象的一个远程代理对这个Binder代理对象的操作会通过驱动最终转发到Binder本地对象上去完成对于一个拥有Binder对象的使用者而言它无须关心这是一个Binder代理对象还是Binder本地对象对于代理对象的操作和对本地对象的操作对它来说没有区别。对于传输过程而言Binder是可以进行跨进程传递的对象Binder驱动会对具有跨进程传递能力的对象做特殊处理自动完成代理对象和本地对象的转换。 面向对象思想的引入将进程间通信转化为通过对某个Binder对象的引用调用该对象的方法而其独特之处在于Binder对象是一个可以跨进程引用的对象它的实体本地对象位于一个进程中而它的引用代理对象却遍布于系统的各个进程之中。最诱人的是这个引用和java里引用一样既可以是强类型也可以是弱类型而且可以从一个进程传给其它进程让大家都能访问同一Server就象将一个对象或引用赋值给另一个引用一样。Binder模糊了进程边界淡化了进程间通信过程整个系统仿佛运行于同一个面向对象的程序之中。形形色色的Binder对象以及星罗棋布的引用仿佛粘接各个应用程序的胶水这也是Binder在英文里的原意。 驱动里面的Binder 我们现在知道Server进程里面的Binder对象指的是Binder本地对象Client里面的对象值得是Binder代理对象在Binder对象进行跨进程传递的时候Binder驱动会自动完成这两种类型的转换因此Binder驱动必然保存了每一个跨越进程的Binder对象的相关信息在驱动中Binder本地对象的代表是一个叫做binder_node的数据结构Binder代理对象是用binder_ref代表的有的地方把Binder本地对象直接称作Binder实体把Binder代理对象直接称作Binder引用句柄其实指的是Binder对象在驱动里面的表现形式读者明白意思即可。 OK现在大致了解Binder的通信模型也了解了Binder这个对象在通信过程中各个组件里面到底表示的是什么。 深入理解Java层的Binder IBinder/IInterface/Binder/BinderProxy/Stub 我们使用AIDL接口的时候经常会接触到这些类那么这每个类代表的是什么呢 IBinder是一个接口它代表了一种跨进程传输的能力只要实现了这个接口就能将这个对象进行跨进程传递这是驱动底层支持的在跨进程数据流经驱动的时候驱动会识别IBinder类型的数据从而自动完成不同进程Binder本地对象以及Binder代理对象的转换。IBinder负责数据传输那么client与server端的调用契约这里不用接口避免混淆呢这里的IInterface代表的就是远程server对象具有什么能力。具体来说就是aidl里面的接口。Java层的Binder类代表的其实就是Binder本地对象。BinderProxy类是Binder类的一个内部类它代表远程进程的Binder对象的本地代理这两个类都继承自IBinder, 因而都具有跨进程传输的能力实际上在跨越进程的时候Binder驱动会自动完成这两个对象的转换。在使用AIDL的时候编译工具会给我们生成一个Stub的静态内部类这个类继承了Binder, 说明它是一个Binder本地对象它实现了IInterface接口表明它具有远程Server承诺给Client的能力Stub是一个抽象类具体的IInterface的相关实现需要我们手动完成这里使用了策略模式。 AIDL过程分析 现在我们通过一个AIDL的使用分析一下整个通信过程中各个角色到底做了什么AIDL到底是如何完成通信的。如果你连AIDL都不熟悉请先查阅官方文档 首先定一个一个简单的aidl接口 1 2 3 4 5// ICompute.aidl package com.example.test.app; interface ICompute {int add(int a, int b); }然后用编译工具编译之后可以得到对应的ICompute.java类看看系统给我们生成的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107package com.example.test.app;public interface ICompute extends android.os.IInterface {/*** Local-side IPC implementation stub class.*/public static abstract class Stub extends android.os.Binder implements com.example.test.app.ICompute {private static final java.lang.String DESCRIPTOR com.example.test.app.ICompute;/*** Construct the stub at attach it to the interface.*/public Stub() {this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an com.example.test.app.ICompute interface,* generating a proxy if needed.*/public static com.example.test.app.ICompute asInterface(android.os.IBinder obj) {if ((obj null)) {return null;}android.os.IInterface iin obj.queryLocalInterface(DESCRIPTOR);if (((iin ! null) (iin instanceof com.example.test.app.ICompute))) {return ((com.example.test.app.ICompute) iin);}return new com.example.test.app.ICompute.Stub.Proxy(obj);}Overridepublic android.os.IBinder asBinder() {return this;}Overridepublic boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_add: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 data.readInt();int _arg1;_arg1 data.readInt();int _result this.add(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.example.test.app.ICompute {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote remote;}Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/Overridepublic int add(int a, int b) throws android.os.RemoteException {android.os.Parcel _data android.os.Parcel.obtain();android.os.Parcel _reply android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(a);_data.writeInt(b);mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);_reply.readException();_result _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_add (android.os.IBinder.FIRST_CALL_TRANSACTION 0);}/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/public int add(int a, int b) throws android.os.RemoteException; }系统帮我们生成了这个文件之后我们只需要继承ICompute.Stub这个抽象类实现它的方法然后在Service 的onBind方法里面返回就实现了AIDL。这个Stub类非常重要具体看看它做了什么。 Stub类继承自Binder意味着这个Stub其实自己是一个Binder本地对象然后实现了ICompute接口ICompute本身是一个IInterface因此他携带某种客户端需要的能力这里是方法add)。此类有一个内部类Proxy也就是Binder代理对象 然后看看asInterface方法我们在bind一个Service之后在onServiceConnecttion的回调里面就是通过这个方法拿到一个远程的service的这个方法做了什么呢 1 2 3 4 5 6 7 8 9 10 11 12 13 14/*** Cast an IBinder object into an com.example.test.app.ICompute interface,* generating a proxy if needed.*/ public static com.example.test.app.ICompute asInterface(android.os.IBinder obj) {if ((obj null)) {return null;}android.os.IInterface iin obj.queryLocalInterface(DESCRIPTOR);if (((iin ! null) (iin instanceof com.example.test.app.ICompute))) {return ((com.example.test.app.ICompute) iin);}return new com.example.test.app.ICompute.Stub.Proxy(obj); }首先看函数的参数IBinder类型的obj这个对象是驱动给我们的如果是Binder本地对象那么它就是Binder类型如果是Binder代理对象那就是BinderProxy类型然后正如上面自动生成的文档所说它会试着查找Binder本地对象如果找到说明Client和Server都在同一个进程这个参数直接就是本地对象直接强制类型转换然后返回如果找不到说明是远程对象处于另外一个进程那么就需要创建一个Binde代理对象让这个Binder代理实现对于远程对象的访问。一般来说如果是与一个远程Service对象进行通信那么这里返回的一定是一个Binder代理对象这个IBinder参数的实际上是BinderProxy; 再看看我们对于aidl的add 方法的实现在Stub类里面add是一个抽象方法我们需要继承这个类并实现它如果Client和Server在同一个进程那么直接就是调用这个方法那么如果是远程调用这中间发生了什么呢Client是如何调用到Server的方法的 我们知道对于远程方法的调用是通过Binder代理完成的在这个例子里面就是Proxy类Proxy对于add方法的实现如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18Override public int add(int a, int b) throws android.os.RemoteException {android.os.Parcel _data android.os.Parcel.obtain();android.os.Parcel _reply android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(a);_data.writeInt(b);mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);_reply.readException();_result _reply.readInt();} finally {_reply.recycle();_data.recycle();}return _result; }它首先用Parcel把数据序列化了然后调用了transact方法这个transact到底做了什么呢这个Proxy类在asInterface方法里面被创建前面提到过如果是Binder代理那么说明驱动返回的IBinder实际是BinderProxy, 因此我们的Proxy类里面的mRemote实际类型应该是BinderProxy我们看看BinderProxy的transact方法(Binder.java的内部类) 1 2public native boolean transact(int code, Parcel data, Parcel reply,int flags) throws RemoteException;这是一个本地方法它的实现在native层具体来说在frameworks/base/core/jni/android_util_Binder.cpp文件里面进行了一系列的函数调用调用链实在太长这里就不给出了要知道的是它最终调用到了talkWithDriver函数看这个函数的名字就知道通信过程要交给驱动完成了这个函数最后通过ioctl系统调用Client进程陷入内核态Client调用add方法的线程挂起等待返回驱动完成一系列的操作之后唤醒Server进程调用了Server进程本地对象的onTransact函数实际上由Server端线程池完成。我们再看Binder本地对象的onTransact方法这里就是Stub类里面的此方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_add: {data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 data.readInt();int _arg1;_arg1 data.readInt();int _result this.add(_arg0, _arg1);reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags); }在Server进程里面onTransact根据调用号每个AIDL函数都有一个编号在跨进程的时候不会传递函数而是传递编号指明调用哪个函数调用相关函数在这个例子里面调用了Binder本地对象的add方法这个方法将结果返回给驱动驱动唤醒挂起的Client进程里面的线程并将结果返回。于是一次跨进程调用就完成了。 至此你应该对AIDL这种通信方式里面的各个类以及各个角色有了一定的了解它总是那么一种固定的模式一个需要跨进程传递的对象一定继承自IBinder如果是Binder本地对象那么一定继承Binder实现IInterface如果是代理对象那么就实现了IInterface并持有了IBinder引用 Proxy与Stub不一样虽然他们都既是Binder又是IInterface不同的是Stub采用的是继承is 关系Proxy采用的是组合has 关系。他们均实现了所有的IInterface函数不同的是Stub又使用策略模式调用的是虚函数待子类实现而Proxy则使用组合模式。为什么Stub采用继承而Proxy采用组合事实上Stub本身is一个IBinderBinder它本身就是一个能跨越进程边界传输的对象所以它得继承IBinder实现transact这个函数从而得到跨越进程的能力这个能力由驱动赋予。Proxy类使用组合是因为他不关心自己是什么它也不需要跨越进程传输它只需要拥有这个能力即可要拥有这个能力只需要保留一个对IBinder的引用。如果把这个过程做一个类比在封建社会Stub好比皇帝可以号令天下他生而具有这个权利不要说宣扬封建迷信。。如果一个人也想号令天下可以“挟天子以令诸侯”。为什么不自己去当皇帝其一一般情况没必要当了皇帝其实限制也蛮多的是不是我现在既能掌管天下又能不受约束Java单继承其二名不正言不顺啊我本来特么就不是Binder你非要我是说不过去搞不好还会造反。最后呢如果想当皇帝也可以那就是asBinder了。在Stub类里面asBinder返回this在Proxy里面返回的是持有的组合类IBinder的引用。 再去翻阅系统的ActivityManagerServer的源码就知道哪一个类是什么角色了IActivityManager是一个IInterface它代表远程Service具有什么能力ActivityManagerNative指的是Binder本地对象类似AIDL工具生成的Stub类这个类是抽象类它的实现是ActivityManagerService因此对于AMS的最终操作都会进入ActivityManagerService这个真正实现同时如果仔细观察ActivityManagerNative.java里面有一个非公开类ActivityManagerProxy, 它代表的就是Binder代理对象是不是跟AIDL模型一模一样呢那么ActivityManager是什么他不过是一个管理类而已可以看到真正的操作都是转发给ActivityManagerNative进而交给他的实现ActivityManagerService 完成的。 OK本文就讲到这里了要深入理解Binder需要自己下功夫那些native层以及驱动里面的调用过程用文章写出来根本没有意义需要自己去跟踪接下来你可以 看Android文档Parcel, IBinder, Binder等涉及到跨进程通信的类不依赖AIDL工具手写远程Service完成跨进程通信看《Binder设计与实现》看老罗的博客或者书书结构更清晰再看《Binder设计与实现》学习Linux系统相关知识自己看源码。
http://www.zqtcl.cn/news/574084/

相关文章:

  • 做衣服类网站策划书高端建设网站企业
  • 珠海网站建设公司有哪些代替做网站推广
  • 泰安的网站建设公司旅游网站建设规划报告怎么写
  • 如何建设淘宝客网站什么是网络营销常用的网络营销方法有哪些
  • 大连华南网站建设深圳网站建设公司的外文名是
  • 做招投标网站云南昆明网站建设价格
  • 越秀区网站建设公司微网站菜单
  • vs2017网站开发广州网站建设易得
  • 长沙企业网站建设价格陕西省门户网站建设政策
  • 龙华营销型网站制作wordpress最近评论
  • 嘉兴微信网站做一个招聘信息的网站_用什么做网站的软件
  • 各种购物网站大全上海市建设工程检测网
  • 网站推广沈阳php网站开发接口开发
  • 莱芜 做网站 公司官网开发
  • tomcat做网站做自媒体查找素材的网站
  • 信阳建设企业网站公司软件开发平台公司
  • 营销型网站建设营销型设计家官网视频
  • 部门网站建设目的加猛挣钱免费做网站软件
  • 洛阳制作网站哪家好wordpress是英文
  • dw里面怎么做网站轮播图网站建设分为多少模块
  • 国外互动网站wordpress设置用户头像
  • 重庆手机网站推广定做net创建网站之后怎么做
  • 网站仿静态做it的兼职网站
  • 建站用wordpress好吗hui怎么做网站
  • 从用户旅程角度做网站分析做网站还是做淘宝
  • 妇科医院网站优化服务商品牌型网站设计推荐
  • 西安网站制作排名网站建设对企业的帮助
  • lamp网站开发 pdf纯html5 网站
  • 白云区同和网站建设购物网站怎么建立
  • 公司制作网站需要espcms易思企业网站管理系统