zoukankan      html  css  js  c++  java
  • Android Binder机制

    Binder是Android系统进程间通信(IPC)方式之一。Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe)、信号(Signal)和跟踪(Trace)、插口(Socket)、报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore)。

    Linux内核的相关知识

    1、进程隔离:进程隔离是为保护操作系统中进程互不干扰而设计的一组不同硬件和软件的技术。操作系统不同进程之间,数据是不共享的。

    2、用户空间/内核空间:Linux Kernel是操作系统的核心,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。kernel有一定的保护机制,把Kernel和上层的应用程序抽像的隔离开,分别称之为Kernel Space和User Space。

    3、系统调用:用户空间访问内核空间的唯一方式。通过这个统一入口接口,所有的资源访问都是在内核的控制下执行,以免导致对用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。

      内核运行态:当一个任务(进程)执行系统调用而陷入内核代码中执行时。

      用户运行态:当进程在执行用户自己的代码时。

    4、内核模块/驱动

      Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信了。

      Binder驱动:在Android系统中,这个运行在内核空间的,负责各个用户进程通过Binder通信的内核模块称为Binder驱动。

    Binder的优势:

      性能和安全。

      Binder相对出传统的Socket方式,更加高效。传统的进程通信方式对于通信双方的身份并没有做出严格的验证,只有在上层协议上进行架设。而Binder机制从协议本身就支持对通信双方做身份校检。

    Binder通信模型

    通信步骤:

    1、SM建立(建立通信录);首先有一个进程向驱动提出申请为SM;驱动同意之后,SM进程负责管理Service(注意这里是Service而不是Server,因为如果通信过程反过来的话,那么原来的客户端Client也会成为服务端Server)不过这时候通信录还是空的,一个号码都没有。

    2、各个Server向SM注册(完善通信录);每个Server端进程启动之后,向SM报告,我是zhangsan, 要找我请返回0x1234(这个地址没有实际意义,类比);其他Server进程依次如此;这样SM就建立了一张表,对应着各个Server的名字和地址;就好比B与A见面了,说存个我的号码吧,以后找我拨打10086。

    3、Client想要与Server通信,首先询问SM;请告诉我如何联系zhangsan,SM收到后给他一个号码0x1234;Client收到之后,开心滴用这个号码拨通了Server的电话,于是就开始通信了。

    Binder负责C/S之间的传输,起到桥梁的作用。
     
    Binder跨进程通信原理

    1、Server进程要向SM注册 ,告知服务器他含有的属性和方法。

    2、Client向SM查询:阐述想要查询的对象,SM通过驱动返回一个一模一样的代理对象和一个模拟方法。

    3、Client获取代理对象,并调用模拟方法,经过传参等一系列操作后返回数据。

    4、Client返回数据过程中经过驱动,驱动收到消息后,通知Server调用其真正的方法,并获取结果,之后驱动将这个结果返回给Client。

      对于Server进程来说,Binder指的是Binder本地对象

        对于Client来说,Binder指的是Binder代理对象

     在驱动中,Binder本地对象的代表是一个叫做binder_node的数据结构,Binder代理对象是用binder_ref代表的,有的地方把Binder本地对象直接称作Binder实体,把Binder代理对象直接称作Binder引用(句柄)。

    深入理解Java层的Binder

    IBinder/IInterface/Binder/BinderProxy/Stub

     IBinder:

    • 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接口:

    package com.example.test.app;
    interface ICompute {
         int add(int a, int b);
    }

    然后用编译工具编译之后,可以得到对应的ICompute.java类。文件中含有ICompute.Stub这个抽象类。我们只需要继承ICompute.Stub这个抽象类,实现它的方法,然后在Service 的onBind方法里面返回就实现了AIDL。

    Stub类

      Stub类继承自Binder,意味着这个Stub其实自己是一个Binder本地对象,然后实现了ICompute接口,ICompute本身是一个IInterface,因此他携带某种客户端需要的能力。此类有一个内部类Proxy,也就是Binder代理对象。

      然后看看asInterface方法,我们在bind一个Service之后,在onServiceConnecttion的回调里面,就是通过这个方法拿到一个远程的service的。

      这个方法里判断Binder是本地对象还是代理对象,从而判断是同进程还是跨进程。

      对于aidl中的方法实现,在Stub中,这个方法是抽象的,需要继承这个类去实现它,如果同进程则直接调用这个方法,如果是跨进程则,则通过Binder代理对象调用。

    总结:一个需要跨进程传递的对象一定继承自IBinder,如果是Binder本地对象,那么一定继承Binder实现IInterface,如果是代理对象,那么就实现了IInterface并持有了IBinder引用;

    参考文献:http://www.jianshu.com/p/af2993526daf

  • 相关阅读:
    bzoj3670 [Noi2014]动物园
    bzoj2882 工艺
    bzoj3097 Hash Killer I
    bzoj3729 Gty的游戏
    【BZOJ4555】[TJOI&HEOI2016]求和 斯特林数+NTT
    【bzoj4869】[Shoi2017]相逢是问候 线段树+扩展欧拉定理
    【BZOJ1853】[Scoi2010]幸运数字 容斥原理+搜索
    【BZOJ2839】集合计数 容斥原理+组合数
    【BZOJ3622】已经没什么好害怕的了 容斥原理+dp
    【BZOJ3589】动态树 树链剖分+线段树
  • 原文地址:https://www.cnblogs.com/yl-saber/p/7368148.html
Copyright © 2011-2022 走看看