美文网首页
Android IPC机制4-ServiceManager的ad

Android IPC机制4-ServiceManager的ad

作者: 朔野 | 来源:发表于2016-06-15 20:53 被阅读3054次

    普通client或者server在获得servicemanger的proxy对象后,肯定就要使用了。对于server来说,主要是调用addService,向serivceManager注册。而client则是通过serivcemanager查询所需server的信息,然后得到server的proxy对象。

    注册服务-addService

    以Native层的服务mediaservice为例,我们先来分析下server是如何向SerivceManager注册的吧

    先来看入口 main_mediaserver.cpp的main函数中的与ServiceManager相关的代码:

    int main(int argc __unused, char** argv)
    {
        ...
    
        //获得ProcessState实例对象
        sp<ProcessState> proc(ProcessState::self());     
        //获取ServiceManager实例对象 【既BpServiceManager】
        sp<IServiceManager> sm = defaultServiceManager(); 
        AudioFlinger::instantiate(); 
        //多媒体服务            
        MediaPlayerService::instantiate();               
        ResourceManagerService::instantiate(); 
        CameraService::instantiate();         
        AudioPolicyService::instantiate();  
        SoundTriggerHwService::instantiate(); 
        RadioService::instantiate(); 
        registerExtensions();
        //创建Binder线程,并加入线程池
        ProcessState::self()->startThreadPool();  
        //当前线程加入到线程池    
        IPCThreadState::self()->joinThreadPool();    
     }
    

    proc(ProcessState::self())

    首先调用的函数是ProcessState::self(),获得ProcessState对象,ProcessState位置在framework\base\libs\binder\ProcessState.cpp,在上一篇文章里有过讲述。其内部有Binder驱动的一些配置,每个进程只有一个。

    获取到ProcessState对象后赋值给了proc变量,程序运行完,proc会自动delete内部的内容,所以就自动释放了先前分配的资源。

    MediaPlayerService:instantiate

    void MediaPlayerService::instantiate() {
        defaultServiceManager()->addService(
               String16("media.player"), new MediaPlayerService()); 
    }
    

    MediaPlayerService的初始化其实就是调用defaultServiceManager的addserivce方法向servicemanager注册,而上一篇已经讲过了defaultServiceManager,此处不在赘述。defaultServiceManager最终得到的是BpServiceManager。
    下面来看看BpServiceManager的addService方法:

    virtual status_t addService(const String16& name, const sp<IBinder>& service,
            bool allowIsolated)
    {
        Parcel data, reply; //Parcel是数据通信包
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());   //先把Interface名字写进去,也就是什么android.os.IServiceManager
        data.writeString16(name);        // name为 "media.player"
        data.writeStrongBinder(service); // MediaPlayerService对象
        data.writeInt32(allowIsolated ? 1 : 0); // allowIsolated= false
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); //
        return err == NO_ERROR ? reply.readExceptionCode() : 
    }
    

    上面函数的核心就是status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); ,而remote()就是创建bpservicemanager时的bpbinder(handle=0)

    BpBinder::transact()

    来看看BpBinder的Transact函数:

    status_t BpBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        if (mAlive) {
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags); 
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }
        return DEAD_OBJECT;
    }
    

    可以发现,transact函数还不是在这个执行的,而是调用的IPCThreadState的transact.

    IPCThreadState::self

    看到这个形式就知道肯定是单例模式了,确实也是这样

    IPCThreadState* IPCThreadState::self()
    {
        if (gHaveTLS) { 
    restart:
            const pthread_key_t k = gTLS;
            IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
            if (st) return st;
            return new IPCThreadState;  //初始IPCThreadState 
        }
        
        if (gShutdown) return NULL;
        
        pthread_mutex_lock(&gTLSMutex);
        if (!gHaveTLS) { //首次进入gHaveTLS为false
            if (pthread_key_create(&gTLS, threadDestructor) != 0) { //创建线程的TLS
                pthread_mutex_unlock(&gTLSMutex);
                return NULL;
            }
            gHaveTLS = true;
        }
        pthread_mutex_unlock(&gTLSMutex);
        goto restart;
    }
    
    IPCThreadState::IPCThreadState()
        : mProcess(ProcessState::self()),
          mMyThreadId(gettid()),    
          mStrictModePolicy(0),
          mLastTransactionBinderFlags(0)
    {
        pthread_setspecific(gTLS, this);
        clearCaller();
        mIn.setDataCapacity(256);
        mOut.setDataCapacity(256);
    }
    

    TLS是指Thread local storage(线程本地储存空间),每个线程都拥有自己的TLS,并且是私有空间,线程之间不会共享,,和java中的ThreadLocal是差不多的概念。通过pthread_getspecific/pthread_setspecific函数可以获取/设置这些空间中的内容。从线程本地存储空间中获得保存在其中的IPCThreadState对象。

    IPCThreadState的构造函数中则是对所属进程,现成id,优先级等做了一些设置。需要注意的是mInmOut,后面会用到。

    IPCThreadState::transact

    回到IPCThreadState::transact这个方法,看看是怎么实现的。

    status_t IPCThreadState::transact(int32_t handle,
                                      uint32_t code, const Parcel& data,
                                      Parcel* reply, uint32_t flags)
    {
        status_t err = data.errorCheck(); //数据错误检查      
        flags |= TF_ACCEPT_FDS;     
        ....
        if (err == NO_ERROR) {
               //调用writeTransactionData 发送数据
            err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
        }
        
        if (err != NO_ERROR) {
            if (reply) reply->setError(err);
            return (mLastError = err);
        }
        
        if ((flags & TF_ONE_WAY) == 0) { //flgs=0进入该分支
            if (reply) {
                //等待响应  
                err = waitForResponse(reply);
            } else {
                Parcel fakeReply;
                err = waitForResponse(&fakeReply);
            }
    
        } else {
            //不需要响应消息的binder则进入该分支
            err = waitForResponse(NULL, NULL); 
        }
        return err;
    }
    

    上面代码的核心就是writeTransactionData 发送数据,waitForResponse等待响应,来看看这两个函数
    writeTransactionData:

    status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
        int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
    {
        binder_transaction_data tr;
    
        tr.target.ptr = 0;
        tr.target.handle = handle; // handle=0
        tr.code = code;            // ADD_SERVICE_TRANSACTION
        tr.flags = binderFlags;    // 0 
        tr.cookie = 0;
        tr.sender_pid = 0;
        tr.sender_euid = 0;
        
        const status_t err = data.errorCheck();
        if (err == NO_ERROR) {
            tr.data_size = data.ipcDataSize();  
            tr.data.ptr.buffer = data.ipcData();
            tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
            tr.data.ptr.offsets = data.ipcObjects();
        } else if (statusBuffer) {
            tr.flags |= TF_STATUS_CODE;
            *statusBuffer = err;
            tr.data_size = sizeof(status_t);
            tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
            tr.offsets_size = 0;
            tr.data.ptr.offsets = 0;
        } else {
            return (mLastError = err);
        }
    //上面把命令数据封装成binder_transaction_data,然后
    //写到mOut中,mOut是命令的缓冲区,也是一个Parcel
        
        mOut.writeInt32(cmd);         //cmd = BC_TRANSACTION
        mOut.write(&tr, sizeof(tr));  //写入binder_transaction_data数据
        
        return NO_ERROR;
    }
    

    其中handle的值用来标识目的端,注册服务过程的目的端为service manager,此处handle=0所对应的是binder_context_mgr_node对象,正是service manager所对应的binder实体对象。binder_transaction_data结构体是binder驱动通信的数据结构,该过程最终是把Binder请求码BC_TRANSACTION和binder_transaction_data结构体写入到mOut。

    再来看看waitForResponse函数

    status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
    {
        int32_t cmd;
        int32_t err;
    
        while (1) {
            if ((err=talkWithDriver()) < NO_ERROR) break; // 
            err = mIn.errorCheck();
            if (err < NO_ERROR) break;
            if (mIn.dataAvail() == 0) continue;
      //这里开始操作mIn了,看来talkWithDriver中
    //把mOut发出去,然后从driver中读到数据放到mIn中了。
            cmd = mIn.readInt32();
    
            switch (cmd) {
            case BR_TRANSACTION_COMPLETE:
                if (!reply && !acquireResult) goto finish;
                break;
            
            case BR_DEAD_REPLY:
                err = DEAD_OBJECT;
                goto finish;
    
            case BR_FAILED_REPLY:
                err = FAILED_TRANSACTION;
                goto finish;
            
            case BR_ACQUIRE_RESULT:
                {
                    const int32_t result = mIn.readInt32();
                    if (!acquireResult) continue;
                    *acquireResult = result ? NO_ERROR : INVALID_OPERATION;
                }
                goto finish;
            
            case BR_REPLY:
                {
                    binder_transaction_data tr;
                    err = mIn.read(&tr, sizeof(tr));
                    if (err != NO_ERROR) goto finish;
    
                    if (reply) {
                        if ((tr.flags & TF_STATUS_CODE) == 0) {
                            reply->ipcSetDataReference(
                                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                                tr.data_size,
                                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                                tr.offsets_size/sizeof(binder_size_t),
                                freeBuffer, this);
                        } else {
                            err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);
                            freeBuffer(NULL,
                                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                                tr.data_size,
                                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                                tr.offsets_size/sizeof(binder_size_t), this);
                        }
                    } else {
                        freeBuffer(NULL,
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(binder_size_t), this);
                        continue;
                    }
                }
                goto finish;
    
            default:
                err = executeCommand(cmd);  //
                if (err != NO_ERROR) goto finish;
                break;
            }
        }
    
    finish:
        if (err != NO_ERROR) {
            if (acquireResult) *acquireResult = err;
            if (reply) reply->setError(err);
            mLastError = err;
        }
        
       
    

    上面代码的细节就不深究了,到这里,我们发送addService的流程就彻底走完了。
    其实就是BpServiceManager发送了一个addService命令到BnServiceManager,然后收到回复。

    回到开始的mediaservice的main函数,在将MediaPlayerService、CameraService、SoundTriggerHwService等服务都初始化后,就会走到下面的语句:

    ProcessState::self()->startThreadPool();  
        //当前线程加入到线程池    
    IPCThreadState::self()->joinThreadPool(); 
    

    进入两个函数内部看看

    ...
    
    看看startThreadPool吧
    
    void ProcessState::startThreadPool()
    
    {
    
      ...
    
        spawnPooledThread(true);
    
    }
    
    void ProcessState::spawnPooledThread(bool isMain)
    
    {
    
        sp<Thread> t = new PoolThread(isMain);isMain是TRUE
    
    //创建线程池,然后run起来,和java的Threadf非常像
    
        t->run(buf);
    
     }
    
    //PoolThread从Thread类中派生,那么此时会产生一个线程吗?看看PoolThread和Thread的构造吧
    
    PoolThread::PoolThread(bool isMain)
    
            : mIsMain(isMain)
    
        {
    
        }
    //再来看看父类
    Thread::Thread(bool canCallJava)//canCallJava默认值是true
    
        :   mCanCallJava(canCallJava),
    
            mThread(thread_id_t(-1)),
    
            mLock("Thread::mLock"),
    
            mStatus(NO_ERROR),
    
            mExitPending(false), mRunning(false)
    
    {
    
    }
    
    //喔,这个时候还没有创建线程呢。然后调用PoolThread::run,实际调用了基类的run。
    
    status_t Thread::run(const char* name, int32_t priority, size_t stack)
    
    {
    
      bool res;
    
        if (mCanCallJava) {
    
            res = createThreadEtc(_threadLoop,//线程函数是_threadLoop
    
                    this, name, priority, stack, &mThread);
    
        }
    
    //终于,在run函数中,创建线程了。从此
    
    //主线程执行IPCThreadState::self()->joinThreadPool();新开的线程执行_threadLoop
    
    //我们先看看_threadLoop
    
    int Thread::_threadLoop(void* user)
    
    {
    
        Thread* const self = static_cast<Thread*>(user);
    
        sp<Thread> strong(self->mHoldSelf);
    
        wp<Thread> weak(strong);
    
        self->mHoldSelf.clear();
    
     
    
        do {
    
     ...
    
            if (result && !self->mExitPending) {
    
                    result = self->threadLoop();哇塞,调用自己的threadLoop
    
                }
    
            }
    
    //我们是PoolThread对象,所以调用PoolThread的threadLoop函数
    
    virtual bool PoolThread ::threadLoop()
    
        {
    
    //mIsMain为true。
    
    //而且注意,这是一个新的线程,所以必然会创建一个
    
    //新的IPCThreadState对象(记得线程本地存储吗?TLS),然后      
    
    IPCThreadState::self()->joinThreadPool(mIsMain);
    
            return false;
    
        }
    
    //主线程和工作线程都调用了joinThreadPool,看看这个干嘛了!
    
    void IPCThreadState::joinThreadPool(bool isMain)
    
    {
    
         mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
    
         status_t result;
    
        do {
    
            int32_t cmd;
    
             result = talkWithDriver();
    
             result = executeCommand(cmd);
    
            }
    
           } while (result != -ECONNREFUSED && result != -EBADF);
    
     
    
        mOut.writeInt32(BC_EXIT_LOOPER);
    
        talkWithDriver(false);
    
    }
    
    //看到没?有loop了,但是好像是有两个线程都执行了这个啊!这里有两个消息循环?
    
    //下面看看executeCommand
    
    status_t IPCThreadState::executeCommand(int32_t cmd)
    
    {
    
    BBinder* obj;
    
        RefBase::weakref_type* refs;
    
        status_t result = NO_ERROR;
    
    case BR_TRANSACTION:
    
            {
    
                binder_transaction_data tr;
    
                result = mIn.read(&tr, sizeof(tr));
    
    //来了一个命令,解析成BR_TRANSACTION,然后读取后续的信息
    
           Parcel reply;
    
                 if (tr.target.ptr) {
    
    //这里用的是BBinder。(因为自己是做server端)
    
                    sp<BBinder> b((BBinder*)tr.cookie);
    
                    const status_t error = b->transact(tr.code, buffer, &reply, 0);
    
    }
    
    //让我们看看BBinder的transact函数干嘛了
    
    status_t BBinder::transact(
    
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    
    {
    
    //就是调用自己的onTransact函数嘛      
    
    err = onTransact(code, data, reply, flags);
    
        return err;
    
    }
    

    BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数
    终于水落石出了,让我们看看BnMediaPlayerServcice的onTransact函数。

    status_t BnMediaPlayerService::onTransact(
    
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    
    {
    
    // BnMediaPlayerService从BBinder和IMediaPlayerService派生,所有IMediaPlayerService
    
    //看到下面的switch没?所有IMediaPlayerService提供的函数都通过命令类型来区分
    
    //
    
        switch(code) {
    
            case CREATE_URL: {
    
                CHECK_INTERFACE(IMediaPlayerService, data, reply);
    
                create是一个虚函数,由MediaPlayerService来实现!!
    
    sp<IMediaPlayer> player = create(
    
                        pid, client, url, numHeaders > 0 ? &headers : NULL);
    
     
    
                reply->writeStrongBinder(player->asBinder());
    
                return NO_ERROR;
    
            } break;
    

    其实,到这里,我们就明白了。BnXXX的onTransact函数收取命令,然后派发到派生类的函数,由他们完成实际的工作。
    说明:
    这里有点特殊,startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。

    小节

    过程分析:

    1. MediaPlayerService进程获得bpservicemanager,通过bpservicemanager对象的bpbinder成员(handl=0)中转到IPCThreadState执行transact

    2. IPCThreadState调用writeTransactionData函数向mout缓冲区写入数据,然后调用waitForResponse等待响应。

    3. mediaservice开启一个工作线程,和主线程一起开始做消息循环,不断的与binder驱动通信,故后续更加需求Binder驱动会增加binder线程个数。

    获取服务-getService

    再来看看client如何通过servicemanager获得server的bpbinder的。

    getService

    首先来看看IServiceManager的getService函数:

    virtual sp<IBinder> getService(const String16& name) const
        {
            unsigned n;
            for (n = 0; n < 5; n++){
                sp<IBinder> svc = checkService(name);
                if (svc != NULL) return svc;
                sleep(1);
            }
            return NULL;
        }
    

    核心是checkService(name),进入代码看看

    virtual sp<IBinder> checkService( const String16& name) const
    {
        Parcel data, reply;
        //写入RPC头
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        //写入服务名
        data.writeString16(name); 
        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); 
        return reply.readStrongBinder();
    }
    
    

    remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);,这句和之前addService的非常类似,肯定又是通过bpservicemanager最终流转到IPCThreadState的transact,只是传递的参数有所不同罢了。 这里就不再讲了。

    总结

    本片文章说是讲ServiceManager的addServicegetService,其实主要还是在分析transact这个函数的执行流转过程,上面有些代码细节我也没有完全弄懂,但我觉得也够了。简单的说ServiceMnager通信的核心有以下几个:

    1. IPCProcessState和IPCThreadState这两个类,他们分别记录了进程和线程中IPC通信需要的相关要素。这两个类都是单例模式,IPCThreadState是最终通信的执行者。
    2. BpBinder:通过handl=0可以直接与ServiceManager的实体Binder通信
    3. Server端会在主线程和一个工作线程开始消息循环,来处理和binder驱动的交互,如有需求再开启新的线程。
    4. 函数调用的流转过程:通过一次次的流转,每个部分都做了需要自己做的事,然后由一个最终的执行者去执行。

    文章里很多部分都来自与gityuaninnost,在此表示感谢!

    相关文章

      网友评论

          本文标题:Android IPC机制4-ServiceManager的ad

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