企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
在socket编程中,当一个socket 关闭后,我们无比希望另一端的select/poll/epoll/WaitForXXX有相应返回,以示通知。 说明:在广域网中,我们常常会因为收不到或者延时收到socket的close消息而烦恼。 在Binder系统中,要是明确表示对BnXXX的生死非常关心,那么在它离世后你会收到一份讣告。你可以嚎啕大哭,或者什么也不做。 关于这个问题,请直接看源码中的例子吧。 1. 表达你的关心 要想收到讣告,必须先要表达你的关心:做下面两件事: - 从IBinder::DeathRecipient派生一个类,并实现其中的通知函数binderDied。这个函数一旦被调用,就相当于你收到了讣告。 - 把这个类注册到系统,告诉你关心哪一个BnXXX的生死。 看示例代码,它在MediaMetadataRetriever.cpp中,如下所示: **MediaMetadataRetriever.cpp** ~~~ const sp<IMediaPlayerService>&MediaMetadataRetriever::getService() { Mutex::Autolock lock(sServiceLock); if(sService.get() == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.player")); if (binder != 0) { break; } usleep(500000); // 0.5 s }while(true); if(sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } //调用下面这个函数,告诉系统我们对这个binder的生死有兴趣 //这个binder是一个BpBinder,它关心的是对端BBinder,也即是BnXXX的父类。 binder->linkToDeath(sDeathNotifier); sService = interface_cast<IMediaPlayerService>(binder); } returnsService; } ~~~ 2. 讣告是怎么收到的? 那么,这份讣告是怎么收到的呢?答案也在executeCommand中,代码如下所示: **IPCThreadState.cpp** ~~~ status_t IPCThreadState::executeCommand(int32_t cmd) { BBinder*obj; RefBase::weakref_type* refs; status_tresult = NO_ERROR; switch(cmd) { caseBR_ERROR: result = mIn.readInt32(); break; ...... caseBR_DEAD_BINDER: { //Binder驱动会通知死亡消息。下面的proxy对应着已经死亡的远端BBinder。 BpBinder *proxy =(BpBinder*)mIn.readInt32(); //发送讣告,Obituary是讣告的意思。最终会传递到你的DeathNotifier中。 proxy->sendObituary(); mOut.writeInt32(BC_DEAD_BINDER_DONE); mOut.writeInt32((int32_t)proxy); }break; default: result = UNKNOWN_ERROR; break; } ~~~ 3. 你死了,我怎么办? 收到讣告后该怎么办呢?有一些代码看起来非常薄情寡义,如下所示: **MediaMetadataRetriever.cpp** ~~~ /* DeathNotifier是MediaMetadataRetriever的内部类,前面在getService函数中 我们注册了它对BnMediaPlayerService的关心。 */ voidMediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>&who) { Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock); //把自己保存的BpMediaPlayerService对象干掉! MediaMetadataRetriever::sService.clear(); LOGW("MediaMetadataRetriever serverdied!");//打印一下LOG,这样就完事大吉了。 } ~~~ 4. 承受不住的诺言 我答应收到讣告后给你送终,可是如果我要是死在你前面或者中途我不想接收讣告,又该怎么办呢?先来看下面的代码: **MediaMetadataRetriever.cpp** ~~~ MediaMetadataRetriever::DeathNotifier::~DeathNotifier() { Mutex::Autolocklock(sServiceLock); // DeathNotifier对象不想活了,但是BnMediaPlayerService还活着, // 或者DeathNotifier中途变卦。怎么办? //unlinkToDeath调用可以取消对BnMediaPlayerService的关心。 if(sService != 0) { sService->asBinder()->unlinkToDeath(this); } } ~~~ Binder的这个讣告是不是很有人情味呢?想知道它是怎么做到的吗?还是先去看看驱动的实现吧。