美文网首页
跟着源码看Binder通信流程

跟着源码看Binder通信流程

作者: _VITA | 来源:发表于2018-05-27 17:23 被阅读0次

    首先看看Binder的详细介绍;https://blog.csdn.net/coding_glacier/article/details/7520199

    大半年前第一次看,基本上看不懂,只是大致有一些印象:Bp,Bn,ServiceManager...

    image.png
    image.png
    • Java应用层: 对于上层应用通过调用AMP.startService, 完全可以不用关心底层,经过层层调用,最终必然会调用到AMS.startService.
    • Java IPC层: Binder通信是采用C/S架构, Android系统的基础架构便已设计好Binder在Java framework层的Binder客户类BinderProxy和服务类Binder;
    • Native IPC层: 对于Native层,如果需要直接使用Binder(比如media相关), 则可以直接使用BpBinder和BBinder(当然这里还有JavaBBinder)即可, 对于上一层Java IPC的通信也是基于这个层面.
    • Kernel物理层: 这里是Binder Driver, 前面3层都跑在用户空间,对于用户空间的内存资源是不共享的,每个Android的进程只能运行在自己进程所拥有的虚拟地址空间, 而内核空间却是可共享的. 真正通信的核心环节还是在Binder Driver.


      image.png
    image.png

    从AudioSystem--IAudioPolicyService--AudioPolicyService一路来看.

    AudioSystem::getOutPut()函数里创建了一个IAudioPolicyService对象:

    
    audio_io_handle_t AudioSystem::getOutput(省略)
    {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return 0;
    return aps->getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
    } 
    
    

    按照通常定义的理解 I某某 都是 某某的Bp端.

    
    const sp<IAudioPolicyService> AudioSystem::get_audio_policy_service()
    {
    省略
    
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder;
    do {
    binder = sm->getService(String16("media.audio_policy"));//在AudioPolicyService.h文件里,static const char *getServiceName() ANDROID_API { return "media.audio_policy"; } 
    
    /*
    
    以下内容对应c语言里
    
     1.初始化binder,打开/dev/binder设备;在内存中为binder映射128K字节空间;
     2.指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要创建一个handle为0的代理binder,这里的代理binder其实就是Bp;
    
    3.通知binder driver(BD)使SM成为BD的context manager;
    4.维护一个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容;即是否有对service的操作要求, 如果有,则调用svcmgr_handler回调来处理请求的操作。
    
    5.SM维护了一个svclist列表来存储service的信息。
    
    */
    
    if (binder != 0)
    break;
    ALOGW("AudioPolicyService not published, waiting...");
    usleep(500000); // 0.5 s
    } while (true);
    ...
    
     // Make sure callbacks can be received by gAudioPolicyServiceClient
    
    // Pool thread的启动:
    ProcessState::self()->startThreadPool();
    
    /*
    
    Pool thread的实际内容则为:
      IPCThreadState::self()->joinThreadPool(); 
    
    IPCThreadState也是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool thread.
    
    ProcessState中有2个Parcel成员,mIn和mOut,Pool thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中,总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在了mOut中。
    
    ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。
    
    BpBinder的transact方法是向IPCThreadState实例发送消息,通知其有消息要发送给BD 
    
    而BBinder则是当IPCThreadState实例收到BD消息时,通过BBinder的transact的方法将其传递给它的子类BnSERVICE的onTransact函数执行server端的操作。
    
    */
    }
    ap = gAudioPolicyService;
    }
    return ap;
    } 
    
    
    image.png

    以上是client端获取Bp端;接下来是Bn端找server的此方法.先是去AudioPolicyService里找AudioPolicyInterfaceImpl,它的实现类,AudioPolicyService里面有很多方法是放在了 AudioPolicyInterfaceImpl.cpp 去实现的.

    
    status_t AudioPolicyService::getOutputForAttr(...){
    ...
    
    //完成client所要求的任务,将
    
    status_t结果返回给client
    
    }
    
    '''
    
    从读代码的角度看了一遍下来,理解一下Binder,然后再对照着开篇的链接去理解Binder会有新的感受
    

    相关文章

      网友评论

          本文标题:跟着源码看Binder通信流程

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