android Binder详解(4)

本文详细分析了Android Binder机制中getService()的过程,包括BpServiceManager::getService()的调用、client端的处理以及service接口的调用流程。此外,还探讨了TF_ONE_WAY异步调用的区别,如client直接返回、不同工作队列的处理,并介绍了DeathRecipient回调的工作原理。最后,总结了Binder在内核中的关键对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


3.4 getService()分析

clinet中获取service接口的调用如下:

    sp<ISampleService> sampleSrv;
    if(getService(String16("SampleService"), &sampleSrv) != NO_ERROR){
        ALOGE("get SampleService fail");
        return 0;
    }
getService()实现如下:

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
    const sp<IServiceManager> sm = defaultServiceManager();
    if (sm != NULL) {
        *outService = interface_cast<INTERFACE>(sm->getService(name));
        if ((*outService) != NULL) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}
这其中获取ServiceManager接口的动作,前面已经分析过了。之后有两个动作:
1,sm->getService(name)获取到一个sp<IBinder>对象。
2,从获取的BpBinder指针中构造出BpSampleService对象。

第二步是很清楚的,就是调用了BpSampleService::interface_cast<ISampleService>(sp<IBinder>)。我们主要需要研究一下第一步的细节。


3.4.1 BpServiceManager::getService()

BpServiceManager::getService()是调用了checkService()函数

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;
            ALOGI("Waiting for service %s...\n", String8(name).string());
            sleep(1);
        }
        return NULL;
    }
virtual sp<IBinder> checkService( const String16& name) const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
        return reply.readStrongBinder();
    }
checkService()中之写入了InterfaceToken和servicename,然后就开始了transact()了。
这边的transact因为没有写入object,流程和PING_TRANSACTION的基本一样了。我们直接到ServiceManager端看看具体的处理。

3.4.2 ServiceManager处理CHECK_SERVICE_TRANSACTION

command和ADD_SERVICE一样在svcmgr_handler()中处理

    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
       //获取service name。
        s = bio_get_string16(msg, &len);
       //查找对应的service。
        ptr = do_find_service(bs, s, len, txn->sender_euid);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        return 0;
主要看下do_find_service()

void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
{
    //根据service name找到对应的svcinfo结点。
    struct svcinfo *si;
    si = find_svc(s, len);
    
//    ALOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
    if (si && si->ptr) {
        if (!si->allow_isolated) {
            // If this service doesn't allow access from isolated processes,
            // then check the uid to see if it is isolated.
            unsigned appid = uid % AID_USER;
            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
                return 0;
            }
        }
    //返回结点中的ptr,这个ptr是binder中对应的binder_ref.desc。
        return si->ptr;
    } else {
        return 0;
    }
}
我们看到了最终返回的是SampleService在ServiceManager这边对应的binder_ref的desc信息,之后这个信息被写入到write buffer中:
void bio_put_ref(struct binder_io *bio, void *ptr)
{ 
    //构造了一个binder_object,也就是一个flat_binder_object。
    struct binder_object *obj;

    if (ptr)
        obj = bio_alloc_obj(bio);
    else
        obj = bio_alloc(bio, sizeof(*obj));

    if (!obj)
        return;

    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj->type = BINDER_TYPE_HANDLE;
    obj->pointer = ptr;
    obj->cookie = 0;
}
之后进入binder_send_reply(),在这里,我们write了BC_FREE_BUFFER,还有一组BC_REPLY信息,BC_REPLY信息中,是在bio_put_ref()中构造的binder_object。
带着这些信息,我们进入到binder中,首先在binder_thread_write()中处理BC_FREE_BUFFER,这边的处理和之前的PING_TRANSACTION基本一致,没有object,释放掉binder_buffer就可以了。
然后处理BC_REPLY,主要在binder_transaction()函数中,这里和addService处理差异在于reply信息是一个object,而不是一个数据,我们看下组织binder_transaction的部分:

        //remote binder object, means BpBinder。
        case BINDER_TYPE_HANDLE:
        case BINDER_TYPE_WEAK_HANDLE: {
            struct binder_ref *ref = binder_get_ref(proc, fp->handle);
            if (ref == NULL) {
                binder_user_error("%d:%d got transaction with invalid handle, %ld\n",
                        proc->pid,
                        thread->pid, fp->handle);
                return_error = BR_FAILED_REPLY;
                goto err_binder_get_ref_failed;
            }
            if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
                return_error = BR_FAILED_REPLY;
                goto err_binder_get_ref_failed;
            }
            //如果传给service所在的进程,转换为BINDER_TYPE_BINDER类型的object。
            if (ref->node->proc == target_proc) {
                if (fp->type == BINDER_TYPE_HANDLE)
                    fp->type = BINDER_TYPE_BINDER;
                else
                    fp->type = BINDER_TYPE_WEAK_BINDER;
                fp->binder = ref->node->ptr;
                fp->cookie = ref->node->cookie;
                binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
                trace_binder_transaction_ref_to_node(t, ref);
                binder_debug(BINDER_DEBUG_TRANSACTION,
                         "        ref %d desc %d -> node %d u%p\n",
                         ref->debug_id, ref->desc, ref->node->debug_id,
                         ref->node->ptr);
            } else {//传入到其他client进程,为目标进程建立新的binder_ref,并传回这个新的binder_ref的信息。
                struct binder_ref *new_ref;
                new_ref = binder_get_ref_for_node(target_proc, ref->node);//第一次会建立一个新的binder_ref。
                if (new_ref == NULL) {
                    return_error = BR_FAILED_REPLY;
                    goto err_binder_get_ref_for_node_failed;
                }
                fp->handle = new_ref->desc;//用目标进程desc替换。
                binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
                trace_binder_transaction_ref_to_ref(t, ref,
                                    new_ref);
                binder_debug(BINDER_DEBUG_TRANSACTION,
                         "        ref %d desc %d -> ref %d desc %d (node %d)\n",
                         ref->debug_id, ref->desc, new_ref->debug_id,
                         new_ref->desc, ref->node->debug_id);
            }
        } break;
在这里,binder会为client进程建立一个新的binder_ref出来,他会在当前进程中得到一个唯一的desc也就是handle值,注意desc值0是保留给了ServiceManager,最终我们把这个handle回填到data中。

3.4.3 client端处理返回信息
client在IPCThreadState::waitForResponse()处理BR_REPLY,数据传递给Parcel reply中,最终调用得到了sp<IBinder>对象。

reply.readStrongBinder();
我们看看readStrongBinder()里面做了什么:
sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}
status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = static_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                //查找对应的BpBinder对象。
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }        
    }
    return BAD_TYPE;
}
最终还是调用了getStrongproxyForHandle()来获取了sp<IBinder>,参数的handle就是在binder中的binder_ref.desc。
getStrongproxyForHandle()中创建BpBinder的动作,我们就不在看了,我们看一下如果不是首次调用的情况下的处理:
} else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
           //force_set()函数和直接赋值的差异在于它会强制调用RefBase.onFirstRef(),对这里来说
           //也就是会出发BpBinder.onFirstRef()。
            result.force_set(b);
            e->refs->decWeak(this);
        }
这段代码中主要注意一下result.fore_set(b)这行代码,这里又强制触发了一次RefBase.onFirstRef(),调用的目的是对binder中的binder_ref增加了一次引用。
但是这里有个问题:
force_set对于binder_ref又增加了一次reference,但是因为他们用的都是同意BpBinder,最终只会调用一次onLastStrongRef()去decrease strong reference,这样会导致ref的增减不同步,可能是会有问题的。(加了debug信息确认,的确是会出现这样的问题的。)


至此,getService()部分分析完毕,我们看到了service的传递主要是依赖binder对于binder_ref的管理,binder_ref.desc决定了在user层的handle,user层又使用handle去建立了一个BpBinder,所有的service访问结构都是使用这个BpBinder构造出BpXXX对象来操作service接口。


3.5 sayHello()调用分析
这部分我们分析下client端调用SampleService的sayHello()接口的流程,看看client端是如何把信息投递到service进程中去的。

3.5.1 sayHello() client调用

virtual int sayHello(const String8& clientName){
        Parcel data,reply;
        data.writeInterfaceToken(ISampleService::getInterfaceDescriptor());
        data.writeString8(clientName);
        remote()->transact(BnSampleService::SAY_HELLO, data, &reply);
        int ret = reply.readInt32();
        ALOGD("sayHello return %d",ret);
        return ret;
    }
这边直接进入到binder中的binder_transaction()函数中去看处理,首先是查找target node的动作:
     if (tr->target.handle) {//handle不为0的情况,这个是一般service的处理。
            struct binder_ref *ref;
            ref = binder_get_ref(proc, tr->target.handle);
            if (ref == NULL) {
                binder_user_error("%d:%d got transaction to invalid handle\n",
                    proc->pid, thread->pid);
                return_error = BR_FAILED_REPLY;
                goto err_invalid_target_handle;
            }
            target_node = ref->node;
        } else {//handle为0,即ServiceManager的case,直接获取binder_context_mgr_node。
            target_node = binder_context_mgr_node;
            if (target_node == NULL) {
                return_error = BR_DEAD_REPLY;
                goto err_no_context_mgr_node;
            }
        }
这部分和ServiceManager不一样,ServieManager的handle always为0,判断handle值为0就可以使用binder_context_mgr_node了。
对于一般service,handle是当前进程中的binder_ref的desc,根据handle我们可以找到对应的binder_ref,而binder_ref.node保存了它所对应的binder_node。
得到了target node之后,可以找到对应的target proc,这样我们就可以把work加入到到对应的进程的todo list中去了。

3.5.2 sayHello() Service端调用

Service端是在IPCThreadState::joinThreadPool()中响应处理的,通过talkWithDriver()和binder打交道,在binder_thread_read()中获取到client传来的信息,流程没有什么特别的,我们注意一下传回来的数据的组织:

        if (t->buffer->target_node) {//transaction cmd时候。
            //对于binder_context_mgr_node,ptr和cookie都为0。
            //对于一般service来说,binder_node中的ptr是service的weakrefs指针,cookie是service的对象指针。(见Parcel中的flatten_binder())
            struct binder_node *target_node = t->buffer->target_node;
            tr.target.ptr = target_node->ptr;
            tr.cookie =  target_node->cookie;
            t->saved_priority = task_nice(current);
            if (t->priority < target_node->min_priority &&
                !(t->flags & TF_ONE_WAY))
                binder_set_nice(t->priority);
            else if (!(t->flags & TF_ONE_WAY) ||
                 t->saved_priority > target_node->min_priority)
                binder_set_nice(target_node->min_priority);
            cmd = BR_TRANSACTION;
        } else {//reply cmd时候,reply时候target_node为null。
            tr.target.ptr = NULL;
            tr.cookie = NULL;
            cmd = BR_REPLY;
        }
注意这边tr.target.ptr和tr.cookie这两个指针,cookie这个就是SampleService的对象。
回到在executeCommand()中处理command:

      case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
            ALOG_ASSERT(result == NO_ERROR,
                "Not enough command data for brTRANSACTION");
            if (result != NO_ERROR) break;
            
            Parcel buffer;
           //将data保存到Parcel中。
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(size_t), freeBuffer, this);
            
            const pid_t origPid = mCallingPid;
            const uid_t origUid = mCallingUid;
            
            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
            
           //调整Priority。
            int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
            if (gDisableBackgroundScheduling) {
                if (curPrio > ANDROID_PRIORITY_NORMAL) {
                    // We have inherited a reduced priority from the caller, but do not
                    // want to run in that state in this process.  The driver set our
                    // priority already (though not our scheduling class), so bounce
                    // it back to the default before invoking the transaction.
                    setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
                }
            } else {
                if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
                    // We want to use the inherited priority from the caller.
                    // Ensure this thread is in the background scheduling class,
                    // since the driver won't modify scheduling classes for us.
                    // The scheduling group is reset to default by the caller
                    // once this method returns after the transaction is complete.
                    set_sched_policy(mMyThreadId, SP_BACKGROUND);
                }
            }

            //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
            
            Parcel reply;
            IF_LOG_TRANSACTIONS() {
                TextOutput::Bundle _b(alog);
                alog << "BR_TRANSACTION thr " << (void*)pthread_self()
                    << " / obj " << tr.target.ptr << " / code "
                    << TypeCode(tr.code) << ": " << indent << buffer
                    << dedent << endl
                    << "Data addr = "
                    << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
                    << ", offsets addr="
                    << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
            }
            if (tr.target.ptr) {//ptr存在的情况下,
                sp<BBinder> b((BBinder*)tr.cookie);//cookie是指向service对象指针,是继承BBinder的,转换为BBinder调用。
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);

            } else {//thre_context_object没有看到被set的地方,目前没有使用到。
                const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);
            }
            
            //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
            //     mCallingPid, origPid, origUid);
            
            if ((tr.flags & TF_ONE_WAY) == 0) {
                LOG_ONEWAY("Sending reply to %d!", mCallingPid);
                sendReply(reply, 0);//发送返回信息。
            } else {
                LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);//不需要返回值的情况。
            }
            
            mCallingPid = origPid;
            mCallingUid = origUid;

            IF_LOG_TRANSACTIONS() {
                TextOutput::Bundle _b(alog);
                alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
                    << tr.target.ptr << ": " << indent << reply << dedent << endl;
            }
            
        }
        break;
调用还是很简单的,从data中读取cookie,就是Service对象的指针,转换为BBinder对象,调用BBinder的transact函数:
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);
            break;
    }

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

    return err;
}
在BBinder::transact()函数中,回去调用我们在BnSampleService中重写的onTransact()函数,最终调用到SampleService::sayHello()了。

调用后,回到executeCommand()中看看sendReply()里面怎么返回的:
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;
    
    return waitForResponse(NULL, NULL);
}
这里和IPCTransaction::transact()一样,调用了writeTransactionData()来组织要写给binder的binder_transaction_data数据,之后调用waitForResponse()来将数据写给binder。
注意binder返回的数据,在executeComand()中被付给了Parcel buffer这个局部对象,在buffer析构的时候,回去free掉内存,不需要我们再去释放了。

3.5.3 sayHello() client端处理reply

reply的处理这里就不说了,和前面所讲到的处理是i一样的,没有任何差别。



3.6 TF_ONE_WAY调用的差别

在前面的分析中,我们已经碰到了很多次TF_ONE_WAY这个flag,在binder中也看不到有些和正常调用不一样的处理,这边我们来写一个TF_ONE_WAY调用的接口来分下TF_ONE_WAY调用的流程上的差异。
首先在SampleService里面加了一个新的接口:

int SampleService::sayHelloAsync(const String8& clientName){
    ALOGD("Async Hello to %s",clientName.string());
    return 0;
}
BpSampleService的实现是:

virtual int sayHelloAsync(const String8& clientName){
        Parcel data,reply;
        data.writeInterfaceToken(ISampleService::getInterfaceDescriptor());
        data.writeString8(clientName);
        remote()->transact(BnSampleService::SAY_HELLO, data, &reply,TF_ONE_WAY);
        int ret = reply.readInt32();
        if(NOT_ENOUGH_DATA == ret)
            ALOGD("for async mode ,there is no reply ~~");
        else
            ALOGD("sayHelloAsync return %d",ret);
        return 0;
    }

3.6.1 client调用过程
在IPCThreadState::transact()中的流程有差异,调用waitForResponse()的reply为NULL:
err = waitForResponse(NULL, NULL);
之后还是调用talkWithDriver()去和binder交互,看看binder部分的差别,我们看有判断TF_ONE_WAY部分的代码就可以了。
binder_transaction()中差异:
if (!reply && !(tr->flags & TF_ONE_WAY))
        t->from = thread;//同步transaction的时候,记录from。
    else
        t->from = NULL;//异步transaction或者reply时候,不需要记录from了。
异步模式的时候,不会在binder_transaction中记录from的thread。



t->buffer = binder_alloc_buf(target_proc, tr->data_size,
        tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
申请binder_buffer的时候,异步模式申请的时候,最后一个参数is_async是为true的,看下binder_alloc_buffer中对于is_async的处理的差异:
if (is_async &&
        proc->free_async_space < size + sizeof(struct binder_buffer)) {
        binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
                 "%d: binder_alloc_buf size %zd failed, no async space left\n",
                  proc->pid, size);
        return NULL;
    }
    buffer->async_transaction = is_async;
    if (is_async) {
        //update free_async_space
        proc->free_async_space -= size + sizeof(struct binder_buffer);
        binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
                 "%d: binder_alloc_buf size %zd async free %zd\n",
                  proc->pid, size, proc->free_async_space);
    }
异步模式下,要检测和更新free_async_space空间,另外就是影响了binder_buffer中的async_transaction的flag。
从这里我们可以看出来free_async_space是对于async调用的一个限制,使用的空间不能超过mmap size的一半。


if (reply) {
        BUG_ON(t->buffer->async_transaction != 0);
        //清除掉binder_tranasaction发起thread的transaction_stack。
        binder_pop_transaction(target_thread, in_reply_to);
    } else if (!(t->flags & TF_ONE_WAY)) {//同步transaction
        BUG_ON(t->buffer->async_transaction != 0);
        t->need_reply = 1;
        //transaction_stack指向当前thread的最后一个binder_transaction,通过from_parent进行链接。
        t->from_parent = thread->transaction_stack;
        thread->transaction_stack = t;
    } else {//异步transaction
        BUG_ON(target_node == NULL);
        BUG_ON(t->buffer->async_transaction != 1);
        if (target_node->has_async_transaction) {
            target_list = &target_node->async_todo;
            target_wait = NULL;
        } else
            target_node->has_async_transaction = 1;
    }
这边TF_ONE_WAY,在这里有比较重大的影响,如果当前没有异步调用的时候,只是设置target_node的has_async_transaction为1,否则的话,为更改target_list为target_node的async_todo,而不是原来的thread/proc的todo list。


之后进入binder_thread_read(),client端在这里是read了BR_TRANSACTION_COMPLETE command后,返回user层,在IPCThreadState::waitForResponse()中进行BR_TRANSACTION_COMPLETE的处理:

case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) goto finish;
            break;
这里我们看到了差异,在异步模式下,reply和acquireResult都是NULL,这里会直接进入finish的代码段,这样waitForResponse()函数就返回了到了我们BpSampleService::sayHelloAsync()中了,这里的reply中没有写入任何的数据。

到这里,client调用已经完全结束了,我们可以清楚看到了异步调用下,我们只是发出command后就退出了,并不会等待service返回BR_REPLY的信息。

3.6.2 service的响应
SampleService还是从binder_thread_read()中读取command:

       if (t->buffer->target_node) {//transaction cmd时候。
            //对于binder_context_mgr_node,ptr和cookie都为0。
            //对于一般service来说,binder_node中的ptr是service的weakrefs指针,cookie是service的对象指针。(见Parcel中的flatten_binder())
            struct binder_node *target_node = t->buffer->target_node;
            tr.target.ptr = target_node->ptr;
            tr.cookie =  target_node->cookie;
            t->saved_priority = task_nice(current);
            //同步模式下设置priority
            if (t->priority < target_node->min_priority &&
                !(t->flags & TF_ONE_WAY))
                binder_set_nice(t->priority);
            else if (!(t->flags & TF_ONE_WAY) ||
                 t->saved_priority > target_node->min_priority)
                binder_set_nice(target_node->min_priority);
            cmd = BR_TRANSACTION;
        } else {//reply cmd时候,reply时候target_node为null。
            tr.target.ptr = NULL;
            tr.cookie = NULL;
            cmd = BR_REPLY;
        }
同步模式下,将client的priority传递给service端。异步模式下,不需要传递,因为client不会等待service的reply。


        //记录sender_pid。
        //异步模式,或者reply情况下,t->from == 0.
        if (t->from) {
            struct task_struct *sender = t->from->proc->tsk;
            tr.sender_pid = task_tgid_nr_ns(sender,
                            task_active_pid_ns(current));
        } else {
            tr.sender_pid = 0;
        }
t->from是client在binder_transaction()中设置的,对于异步模式下,from为NULL。from在这里影响了binder_thread_read()中记录sender_pid,我们后面在user层处理中看到sender_pid。


       if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
            //同步模式下更新stack信息,binder_transaction t会在reply时候在binder_transaction()中pop掉。
            t->to_parent = thread->transaction_stack;
            t->to_thread = thread;
            thread->transaction_stack = t;//把最近读到的binder_transaction设置为transaction_stack
        } else {//异步模式,或者reply时,binder_transaction已经不需要了
            //(reply时候才需要通过binder_transaction找到reply的target thread),在这里直接释放掉。
            t->buffer->transaction = NULL;
            kfree(t);
            binder_stats_deleted(BINDER_STAT_TRANSACTION);
        }
异步模式时候,binder_transaction没有记录到thread->transaction_stack中去,而是直接释放了。因为service不会发送reply信息,也不需要binder_transaction了。

从binder_thread_read()中返回后,回到user层处理读取到的BR_TRANSACTION:

            //client的pid和uid。在异步模式下的时候为0。
            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
异步模式的时候,这里的sender_pid为0,而不是client的真实pid。

另外差异就在于reply的发送,同步模式会发送BC_REPLY给binder,但是对于异步模式来说我们什么都不需要做了。

除去reply之外,我们还要看下freebuffer的处理,Parcel data析构会去调用IPCThreadState::freeBuffer()去发送BC_FREE_BUFFER给binder,我们到binder_thread_write()中看看:

          //异步操作的时候,work会被加入到async_todo的list中,在free时候,把下一个work挪到thread的todo中去。 
          if (buffer->async_transaction && buffer->target_node) {
                BUG_ON(!buffer->target_node->has_async_transaction);
                if (list_empty(&buffer->target_node->async_todo))
                    buffer->target_node->has_async_transaction = 0;
                else
                    list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
            }
这部分代码和之前binder_transaction()中的代码是呼应的,

        if (target_node->has_async_transaction) {
            target_list = &target_node->async_todo;
            target_wait = NULL;
        } else
            target_node->has_async_transaction = 1;
当前的target_node中有异步操作在执行的时候,work加入到了binder_node.async_todo的list中去,当一个async操作完成的时候,再从async_todo中拿出一个新的work加入到thread的todo list中去。
这样的操作逻辑,让异步操作是在一个thread中去完成,因为异步操作的client不会等待,不需要尽快的返回,可以空出更多的thread给同步操作使用。

接着我们看看释放binder_buffer的函数binder_free_buf():

    if (buffer->async_transaction) {
        proc->free_async_space += size + sizeof(struct binder_buffer);

        binder_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
                 "%d: binder_free_buf size %zd async free %zd\n",
                  proc->pid, size, proc->free_async_space);
    }
和申请的时候一样,需要更新一下free_async_space的值。这里我们已经看出来free_async_space是异步操作所能申请的buffer的最大size,每次异步操作申请的时候,会在free_async_space中减掉,而在释放的时候,会增加free_async_space。
free_async_space的最大值是mmap size的一半,也就是说binder要求至少保留一半的内存给同步操作去使用。


3.6.3 小结
异步操作的流程我们已经看完了,差异主要是:
1,client发出异步操作后,直接返回,不等待service reply。
2,client发给service的work,在service在处理其他异步操作时候,会被加入到binder_node.async_todo中去,而不是thread/proc的todo中。
4,client发给service的binder_transaction结构,在service read的时候,会直接释放。
5,client传给service的sender_pid为0。
6,service不会发送BC_REPLY给binder。
7,处理BC_FREE_BUFFER时会检测async_todo是否还有work,如果有,会挪到thread.todo中去执行。



3.7 DeathRecipient调用的分析
在第二章编写SampleService的时候,我们在client调用中调用了linkToDeath()去注册service的died的notification,但是实际跑起来之后,这个callback没有被调用到。
我们这里分析下代码,这个回调是怎么工作的,为什么我们的注册没有工作起来。

client中注册的动作如下:

    DeathCallBack* deathCb = new DeathCallBack();
    sampleSrv->asBinder()->linkToDeath(deathCb);
调用了BpBinder::linkToDeath()

status_t BpBinder::linkToDeath(
    const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
    Obituary ob;
    ob.recipient = recipient;
    ob.cookie = cookie;
    ob.flags = flags;

    LOG_ALWAYS_FATAL_IF(recipient == NULL,
                        "linkToDeath(): recipient must be non-NULL");

    {
        AutoMutex _l(mLock);

        if (!mObitsSent) {//判断BpBinder是否已经die。
            if (!mObituaries) {//构造一个vector来保存注册的DeathRecipient,并发送BC_REQUEST_DEATH_NOTIFICATION给binder。
                mObituaries = new Vector<Obituary>;
                if (!mObituaries) {
                    return NO_MEMORY;
                }
                ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
                getWeakRefs()->incWeak(this);
                IPCThreadState* self = IPCThreadState::self();
                self->requestDeathNotification(mHandle, this);
                self->flushCommands();
            }
            ssize_t res = mObituaries->add(ob);//把注册的DeathRecipient加入到mObituaries。
            return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
        }
    }

    return DEAD_OBJECT;
}
在这里,注册的DeathRecipient是被加入到了mObituaries这个vector里面去了,没有直接传递给binder。
mObituaries创建时候,通过函数requestDeathNotificaiton(),写了一个command BC_REQUEST_DEATH_NOTIFICATION,

status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy)
{
    mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION);
    mOut.writeInt32((int32_t)handle);
    mOut.writeInt32((int32_t)proxy);
    return NO_ERROR;
}
这个command在flushCommands()中被写入到binder :

void IPCThreadState::flushCommands()
{
    if (mProcess->mDriverFD <= 0)
        return;
    talkWithDriver(false);//false表明不会读取command,只是去写command。
}

之后在binder中处理BC_REQUEST_DEATH_NOTIFICATION,之前我们在分析addService()的时候,已经看到了这个command的处理,主要行为就是为当前的binder_ref创建了了一个binder_ref_death对象。


但是我们的问题还没有解决,当service挂掉的时候,是如何被通知到的呢?考service异常退出的时候是不会来得及去和binder做交互的,那么一定是系统帮忙做了什么。
再想到当进程异常退出的时候,系统会帮助我们做file的flush,release的动作来回收资源,binder对于系统来说一样也是个file,所以也会做一样的处理,所以我们关注一下binder_flush()和binder_release():

static int binder_flush(struct file *filp, fl_owner_t id)
{
    struct binder_proc *proc = filp->private_data;
    if(proc->bLogDbg)
        printk("Process %d called flush \n",proc->pid);

    binder_defer_work(proc, BINDER_DEFERRED_FLUSH);

    return 0;
}
这里调用了binder_defer_work():

static void
binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer)
{
    mutex_lock(&binder_deferred_lock);
    proc->deferred_work |= defer;//记录defer work的flag。
    if (hlist_unhashed(&proc->deferred_work_node)) {
        hlist_add_head(&proc->deferred_work_node,
                &binder_deferred_list);
        //将binder_deferred_work放到binder_deferred_workqueue中去。
        queue_work(binder_deferred_workqueue, &binder_deferred_work);
    }
    mutex_unlock(&binder_deferred_lock);
}
所以flush()中,在proc的deferred_work中设上了BINDER_DEFERRED_FLUSH,并在binder_deferred_workqueue中加入了一个新的work。
binder_deferred_workqueue是binder在binder_init()中建立的一个workqueue,任务放到bufferqueue中会被逐个执行。

binder_deferred_work是下面的代码声明

static DECLARE_WORK(binder_deferred_work, binder_deferred_func);
也就是work的执行,就是调用binder_deferred_func()这个函数,

static void binder_deferred_func(struct work_struct *work)
{
    struct binder_proc *proc;
    struct files_struct *files;

    int defer;
    do {
        binder_lock(__func__);
        mutex_lock(&binder_deferred_lock);
        if (!hlist_empty(&binder_deferred_list)) {
            proc = hlist_entry(binder_deferred_list.first,
                    struct binder_proc, deferred_work_node);
            hlist_del_init(&proc->deferred_work_node);
            defer = proc->deferred_work;
            proc->deferred_work = 0;//获取defer的值
        } else {
            proc = NULL;
            defer = 0;
        }
        mutex_unlock(&binder_deferred_lock);

        files = NULL;
        if (defer & BINDER_DEFERRED_PUT_FILES) {
            files = proc->files;
            if (files)
                proc->files = NULL;
        }

        //处理binder_flush()传来的state BINDER_DEFERRED_FLUSH
        if (defer & BINDER_DEFERRED_FLUSH)
            binder_deferred_flush(proc);

        //处理binder_release()传来的state BINDER_DEFERRED_RELEASE
        if (defer & BINDER_DEFERRED_RELEASE)
            binder_deferred_release(proc); /* frees proc */

        binder_unlock(__func__);
        if (files)
            put_files_struct(files);
    } while (proc);
}
最终我们调用了binder_deferred_flush(),

static void binder_deferred_flush(struct binder_proc *proc)
{
    struct rb_node *n;
    int wake_count = 0;
    //让进程所有等待的thread都立刻返回出去。
    for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
        struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
        thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
        if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
            wake_up_interruptible(&thread->wait);
            wake_count++;
        }
    }
    wake_up_interruptible_all(&proc->wait);

    binder_debug(BINDER_DEBUG_OPEN_CLOSE,
             "binder_flush: %d woke %d threads\n", proc->pid,
             wake_count);
}
这个函数中让所有等待的thread,都从等待中退出出去(BINDER_LOOPER_STATE_NEED_RETURN会让thread从binder_thread_read中直接返回出去,即使没有读到任何东西)。


继续看下binder_release(),

static int binder_release(struct inode *nodp, struct file *filp)
{
    struct binder_proc *proc = filp->private_data;
    debugfs_remove(proc->debugfs_entry);
    binder_defer_work(proc, BINDER_DEFERRED_RELEASE);

    return 0;
}
和binder_flush()基本一样,只是push的work的state是BINDER_DEFERRED_RELEASE,看看这个类型在binder_deferred_func()中的处理,

        //处理binder_release()传来的state BINDER_DEFERRED_RELEASE
        if (defer & BINDER_DEFERRED_RELEASE)
            binder_deferred_release(proc); /* frees proc */
调用了binder_deferred_release(),

static void binder_deferred_release(struct binder_proc *proc)
{
    //对当前进程相关的资源做处理。
    struct binder_transaction *t;
    struct rb_node *n;
    int threads, nodes, incoming_refs, outgoing_refs, buffers,
        active_transactions, page_count;

    BUG_ON(proc->vma);
    BUG_ON(proc->files);

    hlist_del(&proc->proc_node);

    if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
        binder_debug(BINDER_DEBUG_DEAD_BINDER,
                 "%s: %d context_mgr_node gone\n",
                 __func__, proc->pid);
        binder_context_mgr_node = NULL;
    }

    threads = 0;
    active_transactions = 0;
    //清除所有的binder_thread对象。
    while ((n = rb_first(&proc->threads))) {
        struct binder_thread *thread;

        thread = rb_entry(n, struct binder_thread, rb_node);
        threads++;
        active_transactions += binder_free_thread(proc, thread);
    }

    nodes = 0;
    incoming_refs = 0;
    //release所有的binder_node对象的资源,当进程中有多个serivce的时候,会有多个binder_node。
    //注意这里只是对binder_node做release动作,并不是delete掉binder_node的对象,这个对象因为client还在引用,所以暂时不会被删除。
    while ((n = rb_first(&proc->nodes))) {
        struct binder_node *node;

        node = rb_entry(n, struct binder_node, rb_node);
        nodes++;
        rb_erase(&node->rb_node, &proc->nodes);
        incoming_refs = binder_node_release(node, incoming_refs);
    }

    outgoing_refs = 0;
    //清除当前进程的reference。
    while ((n = rb_first(&proc->refs_by_desc))) {
        struct binder_ref *ref;

        ref = rb_entry(n, struct binder_ref, rb_node_desc);
        outgoing_refs++;
        binder_delete_ref(ref);
    }

    //清除两个list。
    binder_release_work(&proc->todo);
    binder_release_work(&proc->delivered_death);

    buffers = 0;
    //释放掉已经申请的binder_buffer。
    while ((n = rb_first(&proc->allocated_buffers))) {
        struct binder_buffer *buffer;

        buffer = rb_entry(n, struct binder_buffer, rb_node);

        t = buffer->transaction;
        if (t) {
            t->buffer = NULL;
            buffer->transaction = NULL;
            pr_err("release proc %d, transaction %d, not freed\n",
                   proc->pid, t->debug_id);
            /*BUG();*/
        }

        binder_free_buf(proc, buffer);
        buffers++;
    }

    binder_stats_deleted(BINDER_STAT_PROC);

    //释放mmap的物理page。
    page_count = 0;
    if (proc->pages) {
        int i;

        for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
            void *page_addr;

            if (!proc->pages[i])
                continue;

            page_addr = proc->buffer + i * PAGE_SIZE;
            binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
                     "%s: %d: page %d at %p not freed\n",
                     __func__, proc->pid, i, page_addr);
            unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
            __free_page(proc->pages[i]);
            page_count++;
        }
        kfree(proc->pages);
        vfree(proc->buffer);
    }

    put_task_struct(proc->tsk);

    binder_debug(BINDER_DEBUG_OPEN_CLOSE,
             "%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
             __func__, proc->pid, threads, nodes, incoming_refs,
             outgoing_refs, active_transactions, buffers, page_count);

    kfree(proc);
}
这里我们重点关注一下binder_node的release,这个会设计到client端的binder_ref的处理,

static int binder_node_release(struct binder_node *node, int refs)
{
    struct binder_ref *ref;
    int death = 0;

    list_del_init(&node->work.entry);
    binder_release_work(&node->async_todo);

    if (hlist_empty(&node->refs)) {
        kfree(node);
        binder_stats_deleted(BINDER_STAT_NODE);

        return refs;
    }

    node->proc = NULL;//将proc置空,binder_proc在release之后不会存在了,但是binder_node不会被delete。
    node->local_strong_refs = 0;
    node->local_weak_refs = 0;
    hlist_add_head(&node->dead_node, &binder_dead_nodes);//加入到binder_dead_nodes中去。

    //遍历node对应的所有的binder_ref对象。
    hlist_for_each_entry(ref, &node->refs, node_entry) {
        refs++;

        if (!ref->death)
            continue;

        death++;

        if (list_empty(&ref->death->work.entry)) {//在client的proc.todo中加入BINDER_WORK_DEAD_BINDER work.
            ref->death->work.type = BINDER_WORK_DEAD_BINDER;
            list_add_tail(&ref->death->work.entry,
                      &ref->proc->todo);
            wake_up_interruptible(&ref->proc->wait);
        } else
            BUG();
    }

    binder_debug(BINDER_DEBUG_DEAD_BINDER,
             "node %d now dead, refs %d, death %d\n",
             node->debug_id, refs, death);

    return refs;
}
在这里,binder_node.proc被reset为NULL,遍历了所有的binder_ref,如果binder_ref.death非空,会在binder_ref所在的proc中加入BINDER_WORK_DEAD_BINDER的work。
binder_ref.death正是我们在BC_REQUEST_DEATH_NOTIFICATION中为binder_ref创建的。

这里我们已经看出问题了,client在没有和binder交互的情况下,是不可能处理到BINDER_WORK_DEAD_BINDER这个work的。所以我们在client这段也需要调用一下IPCThreadState::joinThreadPool()。


我们假设已经建立了一个thread的情况继续往下分析。
回到SampleService的client端来,当SampleService挂掉之后,client的todo中有了一个BINDER_WORK_DEAD_BINDER的work。

        case BINDER_WORK_DEAD_BINDER:
        case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
        case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
            struct binder_ref_death *death;
            uint32_t cmd;
            //获取binder_ref_death对象。
            death = container_of(w, struct binder_ref_death, work);
            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
                cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
            else
                cmd = BR_DEAD_BINDER;
            //写回cmd。
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            if (put_user(death->cookie, (void * __user *)ptr))
                return -EFAULT;
            ptr += sizeof(void *);
            binder_stat_br(proc, thread, cmd);
            binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
                     "%d:%d %s %p\n",
                      proc->pid, thread->pid,
                      cmd == BR_DEAD_BINDER ?
                      "BR_DEAD_BINDER" :
                      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
                      death->cookie);

            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                list_del(&w->entry);
                kfree(death);
                binder_stats_deleted(BINDER_STAT_DEATH);
            } else//加入到delivered_death list
                list_move(&w->entry, &proc->delivered_death);
            if (cmd == BR_DEAD_BINDER)
                goto done; /* DEAD_BINDER notifications can cause transactions */
        } break;
这里向user层写回了command BR_DEAD_BINDER,并把当前的work加入到delivered_death list中去。

回到user层后,处理BR_DEAD_BINDER,

         case BR_DEAD_BINDER:
        {
            BpBinder *proxy = (BpBinder*)mIn.readInt32();
            proxy->sendObituary();//调用注册的death callback.
            mOut.writeInt32(BC_DEAD_BINDER_DONE);//写回BC_DEAD_BINDER_DONE,告诉binder已经处理完毕。
            mOut.writeInt32((int32_t)proxy);
        } break;
这里调用了BpBinder::sendObituary(),

void BpBinder::sendObituary()
{
    ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
        this, mHandle, mObitsSent ? "true" : "false");

    mAlive = 0;
    if (mObitsSent) return;

    mLock.lock();
    Vector<Obituary>* obits = mObituaries;
    if(obits != NULL) {
        ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
        IPCThreadState* self = IPCThreadState::self();
        self->clearDeathNotification(mHandle, this);//写BC_CLEAR_DEATH_NOTIFICATION command给binder。
        self->flushCommands();
        mObituaries = NULL;
    }
    mObitsSent = 1;
    mLock.unlock();

    ALOGV("Reporting death of proxy %p for %d recipients\n",
        this, obits ? obits->size() : 0);

    if (obits != NULL) {
        const size_t N = obits->size();
        for (size_t i=0; i<N; i++) {//调用注册在vector中的DeathRecipient。
            reportOneDeath(obits->itemAt(i));
        }

        delete obits;
    }
}
我们注册的DeathRecipient就是保存在了mObituaries这个vecotor,在函数最后的for 循环中,每个注册的DeathRecipient最终被执行。

void BpBinder::reportOneDeath(const Obituary& obit)
{
    sp<DeathRecipient> recipient = obit.recipient.promote();
    ALOGV("Reporting death to recipient: %p\n", recipient.get());
    if (recipient == NULL) return;

    recipient->binderDied(this);
}

处理完BR_DEAD_BINDER之后,client又向binder中写了两个command,BC_CLEAR_DEATH_NOTIFICATION 和 BC_DEAD_BINDER_DONE,再进入binder中看这两个command的处理。
BC_CLEAR_DEATH_NOTIFICATION在binder_thread_write()中是和BC_REQUEST_DEATH_NOTIFICATION在一个case中处理的,他们的处理是相反的, BC_REQUEST_DEATH_NOTIFICATION为当前的binder_ref建立了一个新的binder_ref_death对象,而BC_CLEAR_DEATH_NOTIFICATION是清除了当前的binder_ref.death指针:

} else {
                if (ref->death == NULL) {
                    binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n",
                        proc->pid, thread->pid);
                    break;
                }
                death = ref->death;
                if (death->cookie != cookie) {
                    binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n",
                        proc->pid, thread->pid,
                        death->cookie, cookie);
                    break;
                }
                ref->death = NULL;//清除binder_ref中的death指针。
                if (list_empty(&death->work.entry)) {//death work没有被加入到某个list中,也就是service died还没有被触发。
                    death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
                    if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
                        list_add_tail(&death->work.entry, &thread->todo);
                    } else {
                        list_add_tail(&death->work.entry, &proc->todo);
                        wake_up_interruptible(&proc->wait);
                    }
                } else {//death work已经被加入到list中,也就是 service died已经触发了,修改work type。
                    BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
                    death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
                }
            }
这边根据death work有没有被加入处理的list(也就是对应的service die是否已经出发)来分成两个case分别去看,我们现在的走的else中的流程,在这里death.work(注意这个work是在death.delivered_death这个list中)被修改成了BINDER_WORK_DEAD_BINDER_AND_CLEAR。

之后,binder继续处理BC_DEAD_BINDER_DONE这个command,

case BC_DEAD_BINDER_DONE: {
            struct binder_work *w;
            void __user *cookie;
            struct binder_ref_death *death = NULL;
            if (get_user(cookie, (void __user * __user *)ptr))
                return -EFAULT;

            ptr += sizeof(void *);
            list_for_each_entry(w, &proc->delivered_death, entry) {//根据cookie(user层的BpBinder指针)查找到对应的binder_ref_death。
                struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
                if (tmp_death->cookie == cookie) {
                    death = tmp_death;
                    break;
                }
            }
            binder_debug(BINDER_DEBUG_DEAD_BINDER,
                     "%d:%d BC_DEAD_BINDER_DONE %p found %p\n",
                     proc->pid, thread->pid, cookie, death);
            if (death == NULL) {
                binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n",
                    proc->pid, thread->pid, cookie);
                break;
            }

            list_del_init(&death->work.entry);//从deliver_death list中删除当前的work。
            if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
                death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;//发送BINDER_WORK_CLEAR_DEATH_NOTIFICATION work去清除death。
                if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
                    list_add_tail(&death->work.entry, &thread->todo);
                } else {
                    list_add_tail(&death->work.entry, &proc->todo);
                    wake_up_interruptible(&proc->wait);
                }
            }
        } break;

这边从delivered_death list中删除了death的work,又发了一个新的work BINDER_WORK_CLEAR_DEATH_NOTIFICATION给当前的进程。

从binder_thread_write()中退出后binder在binder_thread_read()中会接受到BINDER_WORK_CLEAR_DEATH_NOTIFICATION进行处理,这个command和前面的BINDER_WORK_DEAD_BINDER是一个case中处理,主要行为,

            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
                cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
            else
                cmd = BR_DEAD_BINDER;
            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                list_del(&w->entry);
                kfree(death);
                binder_stats_deleted(BINDER_STAT_DEATH);
            }
这里又回复给user层一个BR_CLEAR_DEATH_NOTIFICATION_DONE的command,并且释放了之前申请的binder_ref_death对象。
BR_CLEAR_DEATH_NOTIFICATION_DONE在user层处理:

case BR_CLEAR_DEATH_NOTIFICATION_DONE:
        {
            BpBinder *proxy = (BpBinder*)mIn.readInt32();
            proxy->getWeakRefs()->decWeak(proxy);
        } break;
就是对BpBinder做了decrease weak的动作,这个是和BpBinder::linkToDeath()中的下列代码呼应的。
getWeakRefs()->incWeak(this);

到这,整个DeathRecipient的流程就结束了,我们从中也看到了death的回调整个流程是需要client不停的和binder去交互的,所以我们在client中要也要加上IPCThreadState::joinThreadPool()才行。对client的main函数做如下修改后,我们的deathcallback就可以被调用到了。

#if 0
    do{
        sleep(2);
        if(deathCalled){
            ALOGE("death callback called\n");
            break;
        }
    }while(1);
 #else
    IPCThreadState::self()->joinThreadPool(true);
 #endif


四,binder总结

基本上所有的点在上面已经都分析到了。这里list下kernel中的关键对象:
binder_proc:和user层ProcessState对应。
binder_thread:和user层IPCThreadState对应。
binder_node:service在binder中的代表。
binder_ref:client在binder中的代表。
binder_work:传递信息的表达。
binder_proc/binder_thread.todo:维护binder_work,用来传递信息的重要对象。


End!

-------------------------------------------

by sky
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值