[置顶] Binder学习二 MediaServer

以MediaServer为例,进程初始化如下:

1.创建进程中所有Service实例

2.注册service到service manager

3.创建线程池,等待处理binder事件


MediaServer处理原理如下图所示:

[置顶] Binder学习二 MediaServer_第1张图片

上图中,mediaserver的两个线程首先调用binder的ioctl方法并挂起等待binder唤醒,如图中步骤a1和b1所示。其次客户端通过BpXXX发送命令給binder,如步骤a2,b2所示,此时客服端线程将被挂起。binder设备收到请求后首先更新binder_write_read数据结构,然后唤醒挂起的线程,并调用BnXXX::onTransact()执行客户请求。服务端完成处理后将通知binder,binder唤醒客户端线程,从而得到最终结果。


以下为详细调用代码:

frameworks/base/media/mediaserver/Main_mediaserver.cpp

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    MediaPlayerService::instantiate();      //new MediaPlayerService并注册
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    ProcessState::self()->startThreadPool(); //创建线程并调用IPCThreadState::joinThreadPool(true) why??
    IPCThreadState::self()->joinThreadPool(); //在主线程中调用IPCThreadState::joinThreadPool(true)
}

疑点:startThreadPool和joinThreadPool完后有两个线程,主线程和工作线程,而且都在做消息循环,且参数isMain都是true。难道google怕一个线程工作量太多,所以搞两个线程来工作?网上有人测试过把最后一句屏蔽掉,也能正常工作。

frameworks/base/libs/binder/ProcessState.cpp

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
...}

static int open_driver()
{
    if (gSingleProcess) {
        return -1;
    }

    int fd = open("/dev/binder", O_RDWR);
    if (fd >= 0) {
        fcntl(fd, F_SETFD, FD_CLOEXEC); //这里设置为FD_CLOEXEC表示当程序执行exec函数时本fd将被系统自动关闭,表示不传递给exec创建的新进程 ??
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
            LOGE("Binder driver protocol does not match user space protocol!");
            close(fd);
            fd = -1;
        }
#if defined(HAVE_ANDROID_OS)
        size_t maxThreads = 15; //最大线程数为15,此为线程池最大线程个数
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
#endif

    return fd;
}

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);  //这里最终调用到IPCThreadState::self()->joinThreadPool(true)
    }
}
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
        char buf[32];
        sprintf(buf, "Binder Thread #%d", s);
        sp<Thread> t = new PoolThread(isMain);
        t->run(buf);
    }
}

class PoolThread : public Thread
{
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain); //这里最终调用到IPCThreadState::self()->joinThreadPool(mIsMain)
        return false;
    }
    
    const bool mIsMain;
};

frameworks/base/libs/binder/IPCThreadState.cpp

void IPCThreadState::joinThreadPool(bool isMain)
{
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); //为啥多个线程共享同一个Parcel mIn/mOut???
    
...        
    status_t result;
    do {
        int32_t cmd;
...
        // now get the next command to be processed, waiting if necessary
        result = talkWithDriver();
        if (result >= NO_ERROR) {
            size_t IN = mIn.dataAvail();
            if (IN < sizeof(int32_t)) continue;
            cmd = mIn.readInt32();

            result = executeCommand(cmd);
        }
...
        // Let this thread exit the thread pool if it is no longer
        // needed and it is not the main process thread.
        if(result == TIMED_OUT && !isMain) { //非主ThreadPool如果超时,将退出循环
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);
 
    mOut.writeInt32(BC_EXIT_LOOPER); //告诉binder线程退出
    talkWithDriver(false);
}
 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));           
            ...            
            Parcel reply;
            
            if (tr.target.ptr) {
                sp<BBinder> b((BBinder*)tr.cookie);
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); //这里调用transact -> onTransact()
                if (error < NO_ERROR) reply.setError(error);

            } else {
                const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);
            }
            
            if ((tr.flags & TF_ONE_WAY) == 0) {
                sendReply(reply, 0);
            }
            
            mCallingPid = origPid;
            mCallingUid = origUid;            
        }
        break;
    case BR_SPAWN_LOOPER:
        mProcess->spawnPooledThread(false); //线程池中可用线程不足,创建新的线程加入到线程池
        break;
...}

frameworks/base/lib/binder/Binder.cpp

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            reply->writeInt32(pingBinder());
            break;
        default:
            err = onTransact(code, data, reply, flags); //调用到onTransact()
            break;
    }

    if (reply != NULL) {
        reply->setDataPosition(0);
    }

    return err;
}


kernel/omap4/drivers/staging/android/Binder.c

static int binder_thread_read(struct binder_proc *proc,
                  struct binder_thread *thread,
                  void  __user *buffer, int size,
                  signed long *consumed, int non_block)
{
...
retry:
    wait_for_proc_work = thread->transaction_stack == NULL &&
                list_empty(&thread->todo); //如果此线程无事可做,则分配给整个proc使用
...
    thread->looper |= BINDER_LOOPER_STATE_WAITING; //线程标志置位
    if (wait_for_proc_work)
        proc->ready_threads++; //线程进入等待前,进程对应的可用工作线程数+1
    mutex_unlock(&binder_lock);
    if (wait_for_proc_work) {...
        if (non_block) { //单向调用时,直接返回
            if (!binder_has_proc_work(proc, thread))
                ret = -EAGAIN;
        } else
            ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread)); //挂起线程,直到本进程中有事务要做
    } else {
        if (non_block) {
            if (!binder_has_thread_work(thread))
                ret = -EAGAIN;
        } else
            ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));//挂起线程,直到本线程中有事务要做???如果此线程已挂起
    }
    mutex_lock(&binder_lock);
    if (wait_for_proc_work)
        proc->ready_threads--;  //进程可用线程减1
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING; //本线程清除等待标志位

... 
if (proc->requested_threads + proc->ready_threads == 0 &&  //如果尚未申请创建线程或者可用线程为0
	    proc->requested_threads_started < proc->max_threads && //且已创建的线程数小于最大线程数
	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |  //?? 
	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
	     /*spawn a new thread if we leave this out */) {
		proc->requested_threads++;
		binder_debug(BINDER_DEBUG_THREADS,
			     "binder: %d:%d BR_SPAWN_LOOPER\n",
			     proc->pid, thread->pid);
		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer)) //请求binder所在进程创建工作线程
			return -EFAULT;
    }
    return 0;

}

static int binder_has_proc_work(struct binder_proc *proc,                 struct binder_thread *thread) {     return !list_empty(&proc->todo) ||         (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } static int binder_has_thread_work(struct binder_thread *thread) {     return !list_empty(&thread->todo) || thread->return_error != BR_OK ||         (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); }

int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,             void __user *buffer, int size, signed long *consumed) {...

        case BC_REGISTER_LOOPER:             if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {                 thread->looper |= BINDER_LOOPER_STATE_INVALID;                 binder_user_error("binder: %d:%d ERROR:"                     " BC_REGISTER_LOOPER called "                     "after BC_ENTER_LOOPER\n",                     proc->pid, thread->pid);             } else if (proc->requested_threads == 0) {                 thread->looper |= BINDER_LOOPER_STATE_INVALID;                 binder_user_error("binder: %d:%d ERROR:"                     " BC_REGISTER_LOOPER called "                     "without request\n",                     proc->pid, thread->pid);             } else {                 proc->requested_threads--; //申请service进程创建的thread个数减1                 proc->requested_threads_started++; //记录进程中可用的线程数             }             thread->looper |= BINDER_LOOPER_STATE_REGISTERED;             break;

        case BC_ENTER_LOOPER:             thread->looper |= BINDER_LOOPER_STATE_ENTERED;             break; ...




http://wenku.baidu.com/view/f13333d049649b6648d747b3.html Binder深入讲解

http://www.angryredplanet.com/~hackbod/openbinder/docs/html/BinderIPCMechanism.html Openbinder: binder IPC mechanism

http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html Android深入浅出之Binder机制

你可能感兴趣的:(thread,工作,struct,service,user,buffer)