Binder 通信机制

作者: zcwfeng | 来源:发表于2020-07-12 13:11 被阅读0次

    Binder 是什么?
    安卓中的一种IPC的通信机制,了解他的思想,也是贯穿framework源代码很多地方,能够帮助我们更好的理解源代码。他的架构是c/s 架构
    AMS 和 ActivityThread 用到Binder通信机制
    Binder机制支持匿名,相对安全。

    什么时候要用进程间通信?
    开发中WebView的访问,还有图片的加载,推送,双进程守护,下载,闹钟服务,摄像头,电话。

    像支付宝等这些大型应用用的比较多,还有银行类的app

    为什么要多进程?
    可以多进程进行应用保护存活
    cpu 分配给每个应用进程是有限制的,单个进程过多的消耗会导致OOM

    进程间通信为什么用到Binder机制?

    内存划分,分为用户空间和内核控件。
    进程之间的数据是隔离的。
    每个进程有一个自己的用户空间。
    进程之间需要通过内核进行通信。

    性能: Binder 只需要拷贝一次

    特点:C/S 架构相对简单易用

    安全:支持匿名,相对安全

    IPC 传统通信:
    如图,CopyFrom,CopyTo 传输机制拷贝了两次
    Binder 在内核和进程存在一个内存映射,mmap。只有在发送数据的时候copy一次数据,获取直接在内存映射获取数据

    old_ipc binder_ipc

    AIDL 安卓接口定义语言

    github 项目模拟 https://github.com/zcwfeng/zcw_android_demo
    Service
    Client 项目中的AidlClient

    客户端如何获取AIDL遥控器的

    IZcwAidl.Stub.asInterface---调用这个Stub.asInterface 方法
    

    我们定义生成aidl文件的时候系统帮助我们生成了
    public interface IZcwAidl extends android.os.IInterface
    -> class Default 用来定义我们数据的传输

    -> abstract class Stub

        -> asInterface()
        -> onTransact()
    

    -> class Proxy 数据相关的业务

    public static abstract class Stub extends android.os.Binder implements top.zcwfeng.aidl.IZcwAidl
    

    通过这个遥控器是如何调用到服务端的呢?
    服务端又是如何处理的呢

    参考GOOGLE

    binder_aidl

    如果还不够清晰,可以看使用aidl后as帮助我们生成的结构

    实际上Binder是个代理设计模式,属于远程代理

    新建AIDL文件,
    测试方法 addPerson(person)     &     List<Person> getPersonList()
    

    执行过程 addPerson 为例

    client
    // 获取AIDL的方法
    IZcwAidl.Stub.asInterface(service)
    

    客户端:

    调用
    aidl?.addPerson(Person("zcw", 2))
    
    Proxy 里面的方法 实现AIDL接口方法 
    android.os.Parcel _data = android.os.Parcel.obtain();  _data ----     Client 用到了这个
    android.os.Parcel _reply = android.os.Parcel.obtain();  _reply ----服务端返回的数据
    
    addPerson ->
    mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
    

    -> 到了Binder 进行处理

    服务端:

    onTransact 接收处理
    
    case TRANSACTION_addPerson:
    {
    data.enforceInterface(descriptor);
    top.zcwfeng.aidl.Person _arg0;
    if ((0!=data.readInt())) {
    _arg0 =     top.zcwfeng.aidl.Person.CREATOR.createFromParcel(data);
    }
    else {
      _arg0 = null;
    }
    this.addPerson(_arg0);
    reply.writeNoException();
    return true;
    }
    
    aidl_code.png

    整个过程就是:
    client:addPerson-> Proxy ------>mRomote:transact()-----Binder-------onTransact()------->Service:addPerson->Stub

    各种通信机制进行了对比

    ipc_compare

    Framework 服务原理分析

    我们通常使用服务会用getSystemService(Context)

    我们自己实现需要自己实现android.os.Service处理

    bindService(intent,conn, Context.BIND_AUTO_CREATE)

    ContextImpl#bindServiceCommon()
    

    我是api 29 ,发现Google 改来改去就是个坑,所以用23-26看源码吧

    api 23

    ContextImpl#bindServiceCommon()
    
    ActivityManagerNative.getDefault().bindService
    
     ActivityManagerNative.getDefault()--》Proxy.bindService
    
    IActivityManager==IZcwAidl  aidl 接口
    
    ActivityManagerNative == Stub
    
    ActivityManagerProxy == Proxy
    
    
    bindService(app, token, service, resolvedType, conn, fl,
                        callingPackage, userId);===Service
    
    ActivityManagerService === Service
    
    ActivityManagerService#bindServiceLocked()
    
    1.ActiveServices#bringUpServiceLocked()
    
    2.ActiveServices#requestServiceBindingLocked(s, b.intent, callerFg, true);
    
    1
    // APP 已经创建了
    app != null && app.thread != null
     realStartServiceLocked(r, app, execInFg);
        app.thread.scheduleCreateService()
        
        //创建服务的方法
        handleCreateService()
        
        service = (Service) cl.loadClass(data.info.name).newInstance();--->ZcwAidlService
        
    //APP没有创建
     if (app == null)
    
    2
    //绑定与否
    handleBindService();
    
    IBinder binder = s.onBind(data.intent);===>iBinder
    
    
     ActivityManagerNative.getDefault().publishService()===>AMS.publishService()
    
    
    
    c.conn.connected(r.name, service);===>Client=>onServiceConnected()
    
    IServiceConnection conn; 
    ConnectionRecord c
    
    connection.onServiceConnected()
    
    
    IServiceConnection===ServiceDispatcher.InnerConnection
    

    29 变了,mmp的

    ----这里有待清晰描述----


    ActivityManager.getService().bindIsolatedService
    ActivityManager.getService()------>extends IActivityManager.Stub
    IActivityManager--------->相当于Stub
    

    mServices.bindServiceLocked


    A进程访问B进程时的几种状态

    1. 进程B,整个进程都没有启动

    2. 进程B启动了,但是里面的Service没创建出来

    3. 进程B启动了,里面的Service也创建了,但是Service没有被绑定过,回调onBind()

    4. 进程B启动了,里面的Service也创建了,但是Service已经被绑定过,回调onRebind()

    总结,记住这几种关系

    AIDL 接口----->Stub抽象类------>Proxy类----->Stub的实现类
    IZcwAidl----->Stub------>Proxy----->new IZcwAidl.Stub
    IActivityManager---->ActivityManagerNative--->ActivityManagerProxy---->ActivityManagerService

    相关文章

      网友评论

        本文标题:Binder 通信机制

        本文链接:https://www.haomeiwen.com/subject/zesvcktx.html