使用匿名binder实现client向server端的死亡通知

一、引言
因为binder是跨进程通信,难免会遇到服务端出现异常挂死的情况,这个时候需要通知到客户端进行相应的处理,在网络通信中是非常常见的机制,当然,在binder中,Android也为我们写好了相关的框架,但通过binder源码分析,你会发现,服务端挂死能通知到客户端,可是客户端挂死了却不能通知到服务端。有没有别的解决方案呢?分析Android源码,还真发现了一个不错的处理方案—使用匿名binder,简单来说,就是把客户端挂在实名binder下面,让自己成为一个匿名binder的服务端,好像有点绕?没关系,我们挨个分析如下的问题:

1.binder框架是如何实现服务端挂死通知到客户端的?
2.什么是匿名binder?
3.Android源码中匿名binder的巧用

二、DeathRecipient的使用
IBinder类中有一个抽象类DeathRecipient,所有的客户端想要实现服务端对其的死亡通知,都需要实现一个该抽象类的子类:

class DeathRecipient : public virtual RefBase
{
   
public:
    virtual void binderDied(const wp<IBinder>& who) = 0;
};

当服务端出现挂死时,会回调子类的binderDied函数,客户端可在该函数中实现需要的处理。下面看一下客户端是如何注册到服务端的,IBinder类中提供了linkToDeathunlinkToDeath两个纯虚函数用于实现双端关联:

/**
 * Register the @a recipient for a notification if this binder
 * goes away.  If this binder object unexpectedly goes away
 * (typically because its hosting process has been killed),
 * then DeathRecipient::binderDied() will be called with a reference
 * to this.
 *
 * The @a cookie is optional -- if non-NULL, it should be a
 * memory address that you own (that is, you know it is unique).
 *
 * @note You will only receive death notifications for remote binders,
 * as local binders by definition can't die without you dying as well.
 * Trying to use this function on a local binder will result in an
 * INVALID_OPERATION code being returned and nothing happening.
 *
 * @note This link always holds a weak reference to its recipient.
 *
 * @note You will only receive a weak reference to the dead
 * binder.  You should not try to promote this to a strong reference.
 * (Nor should you need to, as there is nothing useful you can
 * directly do with it now that it has passed on.)
 */
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t        linkToDeath(const sp<DeathRecipient>& recipient,
                                    void* cookie = nullptr,
                                    uint32_t flags = 0) = 0;

/**
 * Remove a previously registered death notification.
 * The @a recipient will no longer be called if this object
 * dies.  The @a cookie is optional.  If non-NULL, you can
 * supply a NULL @a recipient, and the recipient previously
 * added with that cookie will be unlinked.
 *
 * If the binder is dead, this will return DEAD_OBJECT. Deleting
 * the object will also unlink all death recipients.
 */
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t        unlinkToDeath(  const wp<DeathRecipient>& recipient,
                                        void* cookie = nullptr,
                                        uint32_t flags = 0,
                                        wp<DeathRecipient>* outRecipient = nullptr) = 0;

binder源码框架中,BBinder和BpBinder均继承自IBinder,那么是否意味着,Bp和Bn都可以实现linkToDeath和unlinkToDeath呢?很遗憾,只有BnBinder才能这么做,上面的注释已经说明了在Bn端调用linkToDeath将会返回非法操作,我们看下源码Binder.cpp:

status_t BBinder::linkToDeath(
    const sp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
    uint32_t /*flags*/)
{
   
    return INVALID_OPERATION;
}

再看下BpBinder.cpp:

// NOLINTNEXTLINE(google-default-arguments)
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 == nullptr,
                        "linkToDeath(): recipient must be non-NULL");

    {
   
        AutoMutex _l
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值