Binder结点死亡通知过程

BpBinder类代表一个远程Binder对象(继承自BpRefBase)的通信功能部分。它提供了linkToDeath方法,供其他对象监听自己所关联的本地结点的死亡通知,本质上是通过调用IPCThreadState类的requestDeathNotification接口。unlinkToDeath方法则是取消接收Binder结点的死亡通知。而sendObituary则是向监听者发送结点的死亡通知。这两个接口都会通过IPCThreadState类的clearDeathNotification向消息处理发送到Binder驱动去处理。

一般BpBinder对象是包含于从BpRefBase继承过来的类中,也即BpINTERFACE类的一个私有成员,代表IPC通信的一方与另一方进行通信。在Binder驱动,要支持死亡通知机制,是通过binder_ref来实现的。binder_ref有一个成员是指向struct binder_ref_death结构的指针。它的结构定义如下:

struct binder_ref_death {

         structbinder_work work;

         binder_uintptr_tcookie;

};

其中,work是指提交给当前线程或进程处理的工作类型,一般为如下三种:             BINDER_WORK_DEAD_BINDER,//dead binder

         BINDER_WORK_DEAD_BINDER_AND_CLEAR,//clear dead binder

         BINDER_WORK_CLEAR_DEATH_NOTIFICATION,//clear death notification

cookie则一般保存的是BpBinder对象的内存地址,主要用于标识当前的通信会话。

 

linkToDeath(…)接口代码分析

该接口的原型如下:

   virtual status_t   linkToDeath(const sp<DeathRecipient>& recipient,

                                    void*cookie = NULL,

                                    uint32_t flags = 0);

使用示例如下,SurfaceFlinger将监听window manager进程的死亡消息:

void SurfaceFlinger::bootFinished()

         。。。

   // wait patiently for the window manager death

   const String16 name("window");

   sp<IBinder> window(defaultServiceManager()->getService(name));

   if (window != 0) {

       window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));

    }

         。。。

 

下面看下linkToDeath方法调用的流程:

BpBinder::linkToDeath(…) --> IPCThreadState::requestDeathNotification(…) --> “BC_REQUEST_DEATH_NOTIFICATION”

 

下面看下处理BC_REQUEST_DEATH_NOTIFICATION的代码逻辑:

由于requestDeathNotification方法传入的两个参数一个是远程Binder结点的句柄以及对象本身的内存地址(BpBinder对象),所以驱动依次拿到这两个参数:

 

int binder_thread_write(struct binder_proc*proc, struct binder_thread *thread,

                            binder_uintptr_tbinder_buffer, size_t size,

                            binder_size_t*consumed)

{

         …

         caseBC_REQUEST_DEATH_NOTIFICATION:

                   caseBC_CLEAR_DEATH_NOTIFICATION: {

                            uint32_ttarget;

                            binder_uintptr_tcookie;

                            structbinder_ref *ref;

                            structbinder_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);

其中通过第一个参数在当前进程找到对应的binder_ref实例,

ref = binder_get_ref(proc, target);

 

下面是处理BC_REQUEST_DEATH_NOTIFICATION的代码:

 

         if(cmd == BC_REQUEST_DEATH_NOTIFICATION) {

                                     如果ref->death不为空,则说明之前已经调用过requestDeathNotification,直接忽略这次调用。

if (ref->death) {

                                               binder_user_error("%d:%dBC_REQUEST_DEATH_NOTIFICATION death notification already set\n",

                                                        proc->pid,thread->pid);

                                              

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值