2

在Binder通信建立后,Client端可能需要知道Server端的存活状态。当Server端挂掉时,Client端需要清理与通信相关的数据和行为,这个清理过程就是通过Binder死亡通知机制实现的。

注册死亡通知

应用层通过调用BpBinder::linkToDeath()来注册死亡通知。Native Binder通信可以直接调用这个接口,Java通信需要通过Jni来调用。

frameworks/base/core/jni/android_util_Binder.cpp

static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 
        jobject recipient, jint flags) // throws RemoteException
{
    ......
    // 获取BpBinder对象
    IBinder* target = (IBinder*)
        env->GetLongField(obj, gBinderProxyOffsets.mObject);                                                                                                                                                
    ......
    // 只有远程传输需要注册死亡通知
    if (!target->localBinder()) {
        // 获取死亡通知队列
        DeathRecipientList* list = (DeathRecipientList*)
                env->GetLongField(obj, gBinderProxyOffsets.mOrgue);
        // 创建JavaDeathRecipient对象,将其加入到死亡回收队列
        sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list);
        // 调用BpBinder::linkToDeath()来建立死亡通知
        status_t err = target->linkToDeath(jdr, NULL, flags);
        ......
    }    
}

处理死亡通知的是JavaDeathRecipient,它继承IBinder::DeathRecipient,接收到死亡通知时会回调binderDied()。

frameworks/base/core/jni/android_util_Binder.cpp

class JavaDeathRecipient : public IBinder::DeathRecipient
{
public:
    JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
          mObjectWeak(NULL), mList(list)
    {
        ......    
        // 加入到回收队列
        list->add(this);

        android_atomic_inc(&gNumDeathRefs);
        // 增加对象引用计数,当创建对象个数达到200时强行出发GC
        incRefsCreated(env);
    }    

    void binderDied(const wp<IBinder>& who) 
    {    
        if (mObject != NULL) {
            JNIEnv* env = javavm_to_jnienv(mVM);                                                                                                                                                            

            // 调用Java的sendDeathNotice方法
            env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
                    gBinderProxyOffsets.mSendDeathNotice, mObject);
            ......
            // 释放全局引用,增加弱引用,以便GC回收
            mObjectWeak = env->NewWeakGlobalRef(mObject);
            env->DeleteGlobalRef(mObject);
            mObject = NULL;
        }    
    }

Java的注册过程最终也是指向到BpBinder中。死亡通知的注销也同样在这里,一起看一下。

frameworks/native/libs/binder/BpBinder.cpp

status_t BpBinder::linkToDeath(
    const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
    Obituary ob; 
    ob.recipient = recipient;
    ob.cookie = cookie;
    ob.flags = flags;
    ......
        // 如果死亡通知已经发出,mObitsSent将被设置
        if (!mObitsSent) {
            // 第一个死亡通知将创建mObituaries,并向驱动注册死亡通知                                                                                                                                                                                  
            if (!mObituaries) {
                mObituaries = new Vector<Obituary>;
                ......
                getWeakRefs()->incWeak(this);
                // 向驱动注册死亡通知
                IPCThreadState* self = IPCThreadState::self();
                self->requestDeathNotification(mHandle, this);
                self->flushCommands();
            }
            // 加入到mObituaries中
            ssize_t res = mObituaries->add(ob);
            return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
        }
    ......
}

status_t BpBinder::unlinkToDeath(
    const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
    wp<DeathRecipient>* outRecipient)
{
    ......
    const size_t N = mObituaries ? mObituaries->size() : 0;
    // 在mObituaries中查找相应的recipient
    for (size_t i=0; i<N; i++) {
        const Obituary& obit = mObituaries->itemAt(i);
        if ((obit.recipient == recipient
                    || (recipient == NULL && obit.cookie == cookie))
                && obit.flags == flags) {
            const uint32_t allFlags = obit.flags|flags;
            if (outRecipient != NULL) {
                *outRecipient = mObituaries->itemAt(i).recipient;
            }
            // 将死亡通知从mObituaries移除
            mObituaries->removeAt(i);
            // 如果是mObituaries中最后一个死亡通知,则像驱动注销死亡通知
            if (mObituaries->size() == 0) {
                ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
                // 与驱动交互
                IPCThreadState* self = IPCThreadState::self();
                self->clearDeathNotification(mHandle, this);
                self->flushCommands();
                delete mObituaries;
                mObituaries = NULL;
            }
            return NO_ERROR;
        }
    }
    ......
}

Obituary翻译过来是讣告的意思,也就是死亡通知,这里用中文解释就有些混乱。一个Binder代理在驱动上只注册一次死亡通知,但是多个应用可以同时注册Obituary到Binder代理上。就是说一个Binder代理接收到死亡通知后可以告诉多个感兴趣的应用,但其都来源于一个死亡通知。真正注册和注销死亡通知是通过IPCThreadState实现的。

frameworks/native/libs/binder/IPCThreadState.cpp

void IPCThreadState::flushCommands()                                                                                                                                                                        
{
    if (mProcess->mDriverFD <= 0)
        return;
    // 向驱动发送命令,不需要回复
    talkWithDriver(false);
}
......
status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy)                                                                                                                          
{
    // 注册死亡通知命令
    mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION);
    mOut.writeInt32((int32_t)handle);
    mOut.writePointer((uintptr_t)proxy);
    return NO_ERROR;
}

status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy)
{
    // 注销死亡通知命令
    mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION);
    mOut.writeInt32((int32_t)handle);
    mOut.writePointer((uintptr_t)proxy);
    return NO_ERROR;
}

接下来进入到驱动中,看看死亡通知命令的处理过程。

drivers/staging/android/binder.c

static int binder_thread_write(struct binder_proc *proc,
            struct binder_thread *thread,
            binder_uintptr_t binder_buffer, size_t size,
            binder_size_t *consumed)
{
    ......
        case BC_REQUEST_DEATH_NOTIFICATION:
        case BC_CLEAR_DEATH_NOTIFICATION: {
            uint32_t target;
            binder_uintptr_t cookie;
            struct binder_ref *ref;
            struct binder_ref_death *death;

            // 获取用户空间数据
            if (get_user(target, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(binder_uintptr_t);
            // 根据handle获取binder引用
            ref = binder_get_ref(proc, target, false);
            ......
            if (cmd == BC_REQUEST_DEATH_NOTIFICATION) 
                ......
                // 分配binder_ref_death结构
                death = kzalloc(sizeof(*death), GFP_KERNEL);
                ......
                binder_stats_created(BINDER_STAT_DEATH);
                // 初始化death工作队列
                INIT_LIST_HEAD(&death->work.entry);
                death->cookie = cookie;
                ref->death = death;
                // 如果proc死掉,发送死亡通知
                if (ref->node->proc == NULL) {
                    ref->death->work.type = BINDER_WORK_DEAD_BINDER;
                    if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
                        list_add_tail(&ref->death->work.entry, &thread->todo);
                    } else {
                        list_add_tail(&ref->death->work.entry, &proc->todo);
                        wake_up_interruptible(&proc->wait);
                    }
                }
            } else {
                ......
                death = ref->death;
                ......
                // 清除binder引用的death
                ref->death = NULL;
                if (list_empty(&death->work.entry)) {
                    // 加入清理死亡通知work到队列
                    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 {
                    // 死亡通知已经发生,修改work的类型
                    BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
                    death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
                }
            }
        } break;
    ......
}

死亡通知的注册过程就是创建一个binder_ref_death结构,赋值给Binder引用的death上,Binder实体死亡时会根据death发送死亡通知。注销死亡通知的过程就是清理Binder引用的death,并创建一个清理的work。

drivers/staging/android/binder.c

static int binder_thread_read(struct binder_proc *proc,
                  struct binder_thread *thread,
                  binder_uintptr_t binder_buffer, size_t size,
                  binder_size_t *consumed, int non_block)
{
    ......
        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;

            death = container_of(w, struct binder_ref_death, work);
            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
                // 注销时回复这个命令
                cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
            Else
                // Binder死亡时回复这个命令
                cmd = BR_DEAD_BINDER;
            ......
            if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
                // 注销时释放death
                list_del(&w->entry);
                kfree(death);
                binder_stats_deleted(BINDER_STAT_DEATH);
            } else
                list_move(&w->entry, &proc->delivered_death);
            if (cmd == BR_DEAD_BINDER)
                goto done; /* DEAD_BINDER notifications can cause transactions */
        } break;
    ......
}

发送死亡通知

Binder进程退出或异常终止时都会调用exit流程,在Binder驱动中会调用到binder_release。Release中会启动一个BINDER_DEFERRED_RELEASE内核workqueue,这里进行具体的清理工作。

drivers/staging/android/binder.c

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

    return 0;
}

static int binder_node_release(struct binder_node *node, int refs)
{
    ......
    list_del_init(&node->work.entry);
    binder_release_work(&node->async_todo);
    ......
    // 循环处理binder实体中的每一个引用
    hlist_for_each_entry(ref, &node->refs, node_entry) {
        ......
        if (list_empty(&ref->death->work.entry)) {
            // 将Binder死亡work加入到进程的todo队列
            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();
    }
    ......
}

static void binder_deferred_release(struct binder_proc *proc)
{
    ......
    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);
        // 释放Binder实体
        incoming_refs = binder_node_release(node, incoming_refs);
    }
    ......
}

Binder驱动处理完release后会将BR_DEAD_BINDER命令发送给应用层。

frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    ......
    case BR_DEAD_BINDER:                                                                                                                                                                                    
        {
            BpBinder *proxy = (BpBinder*)mIn.readPointer();
            // 调用Binder代理的sendObituary
            proxy->sendObituary();
            // 告诉驱动死亡通知已经处理
            mOut.writeInt32(BC_DEAD_BINDER_DONE);
            mOut.writePointer((uintptr_t)proxy);
        } break;
    ......
}

Binder代理处理死亡回收工作,最终回调到binderDied()上。

frameworks/native/libs/binder/BpBinder.cpp

void BpBinder::sendObituary()
{
    ......
    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);
        self->flushCommands();
        mObituaries = NULL;
    }
    // 设置flag,表明收到死亡通知   
    mObitsSent = 1;
    mLock.unlock();
    ......                                                                                                                                                                               
    if (obits != NULL) {
        const size_t N = obits->size();
        // 循环给mObituaries中每一个向量发送死亡通知
        for (size_t i=0; i<N; i++) {
            reportOneDeath(obits->itemAt(i));
        }

        delete obits;
    }   
}

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;
    // 调用上层应用死亡通知的binderDied
    recipient->binderDied(this);
}

戈壁老王
143 声望64 粉丝

做为一个不称职的老年码农,一直疏忽整理笔记,开博记录一下,用来丰富老年生活,