• Android之BInder分析


     

    MediaService的诞生:

    nt main(int argc, char** argv)
    
    {
    
    //FT,就这么简单??
    
    //获得一个ProcessState实例
    
    sp<ProcessState> proc(ProcessState::self());//这里获得一个Process的实例,因为这个实例是单例结构的因此也就是说PorcessState在整个MediaServer这个ServiceManager真个进程里是唯一的共享的
    
    //得到一个ServiceManager对象
    
        sp<IServiceManager> sm = defaultServiceManager();//这里实际上就是使用BINDER_SET_CONTEXT_MGR命令把自己注册成ServiceManger,当Bunder驱动手动这个命令后,就会在驱动内存中实例化一个Binder实体就是BpBInder,事实上每个ServiceManger在刚执行的时候都会向驱动注册ServiceManger
    
        MediaPlayerService::instantiate();//初始化MediaPlayerService服务
    //对于在代码里就向MangerService注册好的Service,自然会在ServiceManger差不多准备好的时候就实例化(其实也是实例化BnBinder),这个实例化后就会放入一个查询表中,同样当服务器端调用addService的时候,Binder驱动也会实例化一个BnBinder并把这个Bnbinder的名字和引用一起放在查询表中。这样Cilent端就能够根据getService来获得服务器的引用,因为在执行getService的时候就是在根据名字查询这个表。
        ProcessState::self()->startThreadPool();//看名字,启动Process的线程池?
    //ProcessState是操作/dev/binder设备的,因为ServiceManger会为很多的Service和Cilent服务就会很多次的操作/dev/binder设备,所以启动线程池来访问binder设备也能加快访问速度(也说明binder设别是支持多线程的)
    
        IPCThreadState::self()->joinThreadPool();//将自己加入到刚才的线程池?
    //Service接受客户端的数据并不是直接接受的而是通过IPCThreadState来调用BnBinder的transact方法,由transact方法来调用Service的onTransact方法实现远程功能的调用的。
    //事实上ServiceMangerAndroid基于BInder C/S结构的守护进程,就是这是一直在监听客户端请求的一端,并能接受的客户端的请求后立即打开一个线程IPCThreadState来为客户端服务,ServieManger打开IPCThreadState后会根据客户端传过来的服务的名字(java端的调用形式为getSystemService(Context.LAYOUT_INFLATER_SERVICE))来查询对应的BnBInder(就是Service在这里注册BInder),然后调用BnBinder的onTranstact来实现。
    
    }

     

     

    ProcessState:

    sp<ProcessState> ProcessState::self()
    
    {
    
        if (gProcess != NULL) return gProcess;---->第一次进来肯定不走这儿
    
        AutoMutex _l(gProcessMutex);--->锁保护
    
        if (gProcess == NULL) gProcess = new ProcessState;--->创建一个ProcessState对象
    
    return gProcess;--->看见没,这里返回的是指针,但是函数返回的是sp<xxx>,所以
    
    //把sp<xxx>看成是XXX*是可以的
    
    }
    
    
    ProcessState::ProcessState()
    
        : mDriverFD(open_driver())----->Android很多代码都是这么写的,稍不留神就没看见这里调用了一个很重要的函数
    
        , mVMStart(MAP_FAILED)//映射内存的起始地址
    
        , mManagesContexts(false)
    
        , mBinderContextCheckFunc(NULL)
    
        , mBinderContextUserData(NULL)
    
        , mThreadPoolStarted(false)
    
        , mThreadPoolSeq(1)
    
    {
    
    if (mDriverFD >= 0) {
    
    //BIDNER_VM_SIZE定义为(1*1024*1024) - (4096 *2) 1M-8K
    
            mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
    
     mDriverFD, 0);//这个需要你自己去man mmap的用法了,不过大概意思就是
    
    //将fd映射为内存,这样内存的memcpy等操作就相当于write/read(fd)了
    
        }
    
        ...
    
    }
  • 相关阅读:
    Deployment progressDeadlineSeconds
    go字符串转[]bytes
    shell单引号内嵌套单引号即可使用变量
    ensp 模拟 calico 跨网段 bgp 网络
    如何利用termination GracePeriodSeconds 优雅地关闭你的服务
    gin是怎么传参数
    垃圾代码评析——关于《C程序设计伴侣》9.4——链表(三)
    垃圾“程序是怎样练成的”——关于《C程序设计伴侣》第A章(五)
    垃圾代码评析——关于《C程序设计伴侣》9.4——链表(四)
    垃圾“程序是怎样炼成的”——关于《C程序设计伴侣》第A章(二)
  • 原文地址:https://www.cnblogs.com/zhanghaiyublog/p/3647467.html
Copyright © 2020-2023  润新知