binder监测连接状态

Binder监测连接状态,以及断开后的重连

一、监测连接状态

1. binder对象死亡通知机制

1.1. 注册死亡通知

client和server通过binder通信,且binder提供一个方法,即传入死亡代理binder.linkToDeath(IBinder.DeathRecipient) ,当client于server断开的时候,client收到DeathRecipient的binderDied()方法回调 ,从而知道连接断开,以下为binder源码:

  • BBinder::linkToDeath ()

    1
    2
    3
    4
    5
    6
    status_t BBinder::linkToDeath(
    const sp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
    uint32_t /*flags*/)
    {
    return INVALID_OPERATION; // 返回无效操作
    }

    server端的linkToDeath只返回无效操作

  • BpBinder::linkToDeath ()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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) { //mObitsSent用来表示Binder驱动程序是否已经向它发送过死亡通知,如果是,直接返回DEAD_OBJECT
    if (!mObituaries) { //第一次注册
    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(); //促使当前线程马上通过IO控制命令BINDER_WRITE_READ进入到Binder驱动程序中,以便可以执行注册死亡接受通知的操作
    }
    ssize_t res = mObituaries->add(ob); //非第一个注册
    return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
    }
    }

    return DEAD_OBJECT;
    }

    Binder代理对象内部的成员变量mObitsSent用来表示Binder驱动程序是否已经向它发送过死亡通知

    • 若是,表示Binder本地对象已经死亡,返回DEAD_OBJECT
    • 若否,
      • 若第一次注册,记录Binder代理对象的地址,并立马调用Binder Driver执行注册死亡通知
      • 非第一次注册,直接加入死亡通知对象列表mObituaries
  • binderDied()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class IBinder : public virtual RefBase
    {
    public:

    class DeathRecipient : public virtual RefBase
    {
    public:
    virtual void binderDied(const wp<IBinder>& who) = 0;//重写父类DeathRecipient的成员函数binderDied
    };

    ......
    };

    自定义的死亡通知接受者必须要重写父类DeathRecipient的成员函数binderDied。当Binder驱动程序通知一个Binder代理对象它所引用的Binder本地对象已经死亡时,就会调用它所指定的死亡通知接受者的成员函数binderDied

  • 简述流程

    • Binder代理对象将一个死亡接收通知注册到Binder驱动程序中
    • 当Binder驱动程序监控到它所引用的Binder本地对象死亡时,Binder驱动程序就会向Binder代理对象发送一个死亡通知

    由BBinder::linkToDeath ()和BpBinder::linkToDeath ()代码可见

    • server进程死亡时,运行在其里的Binder对象就死亡,通过比较Binder代理存在,本地对象为空可知server端死亡,会通知到client代理对象,pmcs模块中即为BnPmcsProxy对象
    • client进程死亡时,没有通知任何对象。这时候Binder驱动程序就应该向那些引用了它的Binder代理对象发送死亡接受通知,以便它们可以知道自己引用了一个无效的Binder本地对象
  • 一句话总结

    client可以知道连接断开,server不知道什么时候断开,只有通过连接它的client来获得连接状态

1.2. 发送死亡接收通知

​ 暂略

2. client检测连接状态

由 binder对象死亡通知机制 可知,client端(PmcsProxy )可通过binder.linkToDeath(IBinder.DeathRecipient)获得连接状态,即server挂掉,通知Binder代理对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool PmcsProxy::attachServer()
{
const sp<IPmcsService>& service(getPmcsService());

if(service.get() != NULL)
{
if (mDeathNotifier == NULL) {
mDeathNotifier = new DeathNotifier<PmcsProxy>(this);
}
service->asBinder()->linkToDeath(mDeathNotifier); // 注册死亡通知
return true;
}
return false;
}

3. server检测连接状态

由 binder对象死亡通知机制 可知,server自身无法检测连接状态,只能通过与server端连接的client端来获取连接状态,即通过client端(PmcsProxy )的binder.linkToDeath(IBinder.DeathRecipient),那么server端只要获取到client对象就可以检测连接状态

  • server如何获取和区分client?两种方法
    • server端给每个连接上的client端一个标识token
      • client类增加一个token属性
      • 当创建一个client时,server给其分配一个token标识
    • 利用Binder的static方法,Binder.getCallingPid()来拿到client端的pid

二、连接断开后的重连

由上文 监测连接状态 可知,在重写binderDied函数时,再次连接就好了

  • client检测到server断开,client重启server
  • server检测到client断开,server重创建一个client
-------------本文结束感谢您的阅读-------------
显示 Gitment 评论