android binder 机制 (ServiceManager)

本文详细剖析了Android系统中Binder机制的工作原理,重点介绍了ServiceManager的角色及其内部实现细节,包括客户端和服务端之间的通信流程。

Binder机制作为一种IPC通信机制,在Android系统中扮演了非常重要的角色,因此我也花了一些时间来研究它,按照我的理解,下面我将从4个方面来讲一下Binder,如有不对的地方,还希望大家多多指教。下面的例子都将以MediaServer来讲。

一、ServiceManager

ServiceManager在Binder系统中相当与DNS,Server会先在这里注册,然后Client会在这里查询服务以获得与Service所在的Server进程建立通信的通路。

在与ServiceManager的通信中,书上是以addService为例来讲,我这里将以getService为例来讲。直接上代码。

  1. /*static*/const sp<IMediaPlayerService>&  
  2. IMediaDeathNotifier::getMediaPlayerService()  
  3. {  
  4.     ALOGV("getMediaPlayerService");  
  5.     Mutex::Autolock _l(sServiceLock);  
  6.     if (sMediaPlayerService == 0) {  
  7.         sp<IServiceManager> sm = defaultServiceManager();  
  8.         sp<IBinder> binder;  
  9.         do {  
  10.             binder = sm->getService(String16("media.player"));  
  11.             if (binder != 0) {  
  12.                 break;  
  13.             }  
  14.             ALOGW("Media player service not published, waiting...");  
  15.             usleep(500000); // 0.5 s  
  16.         } while (true);  
  17.   
  18.         if (sDeathNotifier == NULL) {  
  19.             sDeathNotifier = new DeathNotifier();  
  20.         }  
  21.         binder->linkToDeath(sDeathNotifier);  
  22.         sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);  
  23.     }  
  24.     ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");  
  25.     return sMediaPlayerService;  
  26. }  

首先我们来看defaultServiceManager(),这是一个单例模式,实现如下:

  1. sp<IServiceManager> defaultServiceManager() {  
  2.     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;  
  3.       
  4.     {  
  5.         AutoMutex _l(gDefaultServiceManagerLock);  
  6.         while (gDefaultServiceManager == NULL) {  
  7.             gDefaultServiceManager = interface_cast<IServiceManager>(  
  8.                 ProcessState::self()->getContextObject(NULL));  
  9.             if (gDefaultServiceManager == NULL)  
  10.                 sleep(1);  
  11.         }  
  12.     }  
  13.       
  14.     return gDefaultServiceManager;  
  15. }  

其中,ProcessState::self()->getContextObject(NULL)会返回一个BpBinder(0),那么就有:

       gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));

根据interface_cast的定义,就变成了:

       gDefaultServiceManager =BpServiceManager(BpBinder(0));

接下来看下面这句话的实现:

binder = sm->getService(String16("media.player"));

       由前面的分析,sm为BpServiceManager的实例,我们直接到IserviceManager.cpp里面找到BpServiceManager的实现,并找到getService方法,其核心实现调用了checkService方法,实现如下:


  1. virtual sp<IBinder> checkService( const String16& name) const  
  2. {  
  3.      Parcel data, reply;  
  4.      data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  5.      data.writeString16(name);  
  6.      remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);  
  7.      return reply.readStrongBinder();  
  8. }  

这里,我们会有一个疑问:remote()返回什么。

       先看BpServiceManager的定义:

classBpServiceManager : public BpInterface<IServiceManager>

      

template<typenameINTERFACE>

classBpInterface : public INTERFACE, public BpRefBase

把模板替换一下,变成

classBpInterface : public IServiceManager, public BpRefBase

OK,在BpRefBase里面找到了remote()的定义:

inline IBinder* remote(){ return mRemote; }

 

mRemote什么时候赋值的呢?我们再来看BpServiceManager的构造函数:
  1. BpServiceManager(const sp<IBinder>& impl)  
  2.         : BpInterface<IServiceManager>(impl)  
  3. {  
  4. }  
  1. inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)  
  2.     : BpRefBase(remote)  
  3. {  
  4. }  
  1. BpRefBase::BpRefBase(const sp<IBinder>& o)  
  2.     : mRemote(o.get()), mRefs(NULL), mState(0)  
  3. {  
  4.     extendObjectLifetime(OBJECT_LIFETIME_WEAK);  
  5.   
  6.     if (mRemote) {  
  7.         mRemote->incStrong(this);           // Removed on first IncStrong().  
  8.         mRefs = mRemote->createWeak(this);  // Held for our entire lifetime.  
  9.     }  
  10. }  
至此,我们就可以知道remote()返回的是之前创建的BpBinder对象BpBinder(0)。那么remote()->transact()实际上就是调用了BpBinder的transact方法。我们跳到BpBinder里面,来看看transact的实现:
  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // Once a binder has died, it will never come back to life.  
  5.     if (mAlive) {  
  6.         status_t status = IPCThreadState::self()->transact(  
  7.             mHandle, code, data, reply, flags);  
  8.         if (status == DEAD_OBJECT) mAlive = 0;  
  9.         return status;  
  10.     }  
  11.   
  12.     return DEAD_OBJECT;  
  13. }  
它把工作都交给IPCThreadState来做了。IPCThreadState是什么呢?它就是Binder传输数据中真正干活的伙计,每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn,一个mOut,其中,mIn用来接收来自Binder设备的数据,mOut用来存储发往Binder设备的数据。OK,我们继续跳到IPCThreadState里面来。
  1. status_t IPCThreadState::transact(int32_t handle,  
  2.                                   uint32_t code, const Parcel& data,  
  3.                                   Parcel* reply, uint32_t flags)  
  4. {  
  5.     status_t err = data.errorCheck();  
  6.     flags |= TF_ACCEPT_FDS;  
  7.     ……  
  8.     err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  9.     ……  
  10.     err = waitForResponse(reply);  
  11.     ……  
  12.     return err;  
  13. }  
  14.   
  15. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
  16.     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)  
  17. {  
  18.     binder_transaction_data tr;  
  19.   
  20.     tr.target.handle = handle;  
  21.     tr.code = code;  
  22.     tr.flags = binderFlags;  
  23.     tr.cookie = 0;  
  24.     tr.sender_pid = 0;  
  25.     tr.sender_euid = 0;  
  26.       
  27.     const status_t err = data.errorCheck();  
  28.     if (err == NO_ERROR) {  
  29.         tr.data_size = data.ipcDataSize();  
  30.         tr.data.ptr.buffer = data.ipcData();  
  31.         tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  32.         tr.data.ptr.offsets = data.ipcObjects();  
  33.     } else if (statusBuffer) {  
  34.         tr.flags |= TF_STATUS_CODE;  
  35.         *statusBuffer = err;  
  36.         tr.data_size = sizeof(status_t);  
  37.         tr.data.ptr.buffer = statusBuffer;  
  38.         tr.offsets_size = 0;  
  39.         tr.data.ptr.offsets = NULL;  
  40.     } else {  
  41.         return (mLastError = err);  
  42.     }  
  43.       
  44.     mOut.writeInt32(cmd);  
  45.     mOut.write(&tr, sizeof(tr));  
  46.       
  47.     return NO_ERROR;  
  48. }  
writeTransactionData仅仅是把数据写到了mOut里面等待发送给Binder,接下来就waitForResponse。
  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)  
  2. {  
  3.     int32_t cmd;  
  4.     int32_t err;  
  5.   
  6.     while (1) {  
  7.         if ((err=talkWithDriver()) < NO_ERROR) break;  
  8.         err = mIn.errorCheck();  
  9.         if (err < NO_ERROR) break;  
  10.         if (mIn.dataAvail() == 0) continue;  
  11.           
  12.         cmd = mIn.readInt32();  
  13.           
  14.         switch (cmd) {  
  15.         …  
  16.         case BR_REPLY:  
  17.             {  
  18.                 binder_transaction_data tr;  
  19.                 err = mIn.read(&tr, sizeof(tr));  
  20.                 if (err != NO_ERROR) goto finish;  
  21.                 if (reply) {  
  22.                     if ((tr.flags & TF_STATUS_CODE) == 0) {  
  23.                         reply->ipcSetDataReference(  
  24.                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  25.                             tr.data_size,  
  26.                             reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  27.                             tr.offsets_size/sizeof(size_t),  
  28.                             freeBuffer, this);  
  29.                     } else {  
  30.                         err = *static_cast<const status_t*>(tr.data.ptr.buffer);  
  31.                         freeBuffer(NULL,  
  32.                             reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  33.                             tr.data_size,  
  34.                             reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  35.                             tr.offsets_size/sizeof(size_t), this);  
  36.                     }  
  37.                 } else {  
  38.                     freeBuffer(NULL,  
  39.                         reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  40.                         tr.data_size,  
  41.                         reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  42.                         tr.offsets_size/sizeof(size_t), this);  
  43.                     continue;  
  44.                 }  
  45.             }  
  46.             goto finish;  
  47.         ……  
  48.   
  49.         default:  
  50.             err = executeCommand(cmd);  
  51.             if (err != NO_ERROR) goto finish;  
  52.             break;  
  53.         }  
  54.     }  
  55.   
  56. finish:  
  57.     if (err != NO_ERROR) {  
  58.         if (acquireResult) *acquireResult = err;  
  59.         if (reply) reply->setError(err);  
  60.         mLastError = err;  
  61.     }  
  62.       
  63.     return err;  
  64. }  
看,它在不停的talkWithDriver,看字面意思,应该是在这个函数里面操作了Binder驱动,让我们一探究竟吧。
  1. status_t IPCThreadState::talkWithDriver(bool doReceive)  
  2. {  
  3.     if (mProcess->mDriverFD <= 0) {  
  4.         return -EBADF;  
  5.     }  
  6.       
  7.     binder_write_read bwr;  
  8.       
  9.     // Is the read buffer empty?  
  10.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  11.       
  12.     // We don't want to write anything if we are still reading  
  13.     // from data left in the input buffer and the caller  
  14.     // has requested to read the next data.  
  15.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  16.       
  17.     bwr.write_size = outAvail;  
  18.     bwr.write_buffer = (long unsigned int)mOut.data();  
  19.   
  20.     // This is what we'll read.  
  21.     if (doReceive && needRead) {  
  22.         bwr.read_size = mIn.dataCapacity();  
  23.         bwr.read_buffer = (long unsigned int)mIn.data();  
  24.     } else {  
  25.         bwr.read_size = 0;  
  26.         bwr.read_buffer = 0;  
  27.     }  
  28.       
  29.     // Return immediately if there is nothing to do.  
  30.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  31.   
  32.     bwr.write_consumed = 0;  
  33.     bwr.read_consumed = 0;  
  34.     status_t err;  
  35.     do {  
  36.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  37.             err = NO_ERROR;  
  38.         else  
  39.             err = -errno;  
  40.   
  41.         if (mProcess->mDriverFD <= 0) {  
  42.             err = -EBADF;  
  43.         }  
  44.     } while (err == -EINTR);  
  45.   
  46.     if (err >= NO_ERROR) {  
  47.         if (bwr.write_consumed > 0) {  
  48.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  49.                 mOut.remove(0, bwr.write_consumed);  
  50.             else  
  51.                 mOut.setDataSize(0);  
  52.         }  
  53.         if (bwr.read_consumed > 0) {  
  54.             mIn.setDataSize(bwr.read_consumed);  
  55.             mIn.setDataPosition(0);  
  56.         }  
  57.         return NO_ERROR;  
  58.     }  
  59.       
  60.     return err;  
  61. }  

在talkWithDriver中,IPCThreadState不断的写和读取Binder驱动,于是首先writeTransactionData中mOut中准备的数据被写到了Binder驱动,之后,便开始等待Binder中有新的数据出现,谁会往里面写数据呢?应该是目标进程才对,且让我们来看一下这部分是怎么实现的吧。

在Binder IPC通信过程中,进程间通信都要先通过向Binder驱动发送BC_XXX命令,然后Binder 驱动稍做处理后通过对应的BR_XXX将命令转给给目标进程。

如果有返回值,进程也是先将返回结果以BC_REPLY的形式先发给Binder驱动,然后通过驱动以BR_REPLY命令转发。



Binder1往Driver中写数据后,Binder驱动首先会判断当前命令接收方是Service Manager还是普通的Server端,判断依据是tr->target.handle.if(tr->target.handle == 0)   表示该命令是发送特殊结点,即Service Manager,而else  针对一般情况,我们需要判断Binder驱动中有没有对应的结点引用,正常情况下应该是能够找到handle对应的Binder结点引用的。通过结点引用,我们就可以定位到处理命令的Binder结点(实体结点)。

在上面的writeTransactionData中,tr->target.handle == 0,故Service Manager进程会收到BR_TRANSACTION命令,Service Manager在处理完命令后,会把结果通过BC_REPLY消息写回Binder驱动,使得上面的waitForResponse(存在与Client进程中)可以得到BR_REPLY的response,从而完成一次交互。

接下来,我们先跳到Service_Manager.c中,来看看Service Manager进程是怎么处理BR_TRANSACTION命令的。
  1. int main(int argc, char **argv)  
  2. {  
  3.     struct binder_state *bs;  
  4.     void *svcmgr = BINDER_SERVICE_MANAGER;  
  5.   
  6.     bs = binder_open(128*1024);  
  7.   
  8.     if (binder_become_context_manager(bs)) {  
  9.         ALOGE("cannot become context manager (%s)\n", strerror(errno));  
  10.         return -1;  
  11.     }  
  12.   
  13.     svcmgr_handle = svcmgr;  
  14.     binder_loop(bs, svcmgr_handler);  
  15.     return 0;  
  16. }  
  17.   
  18. void binder_loop(struct binder_state *bs, binder_handler func)  
  19. {  
  20.     int res;  
  21.     struct binder_write_read bwr;  
  22.     unsigned readbuf[32];  
  23.   
  24.     bwr.write_size = 0;  
  25.     bwr.write_consumed = 0;  
  26.     bwr.write_buffer = 0;  
  27.       
  28.     readbuf[0] = BC_ENTER_LOOPER;  
  29.     binder_write(bs, readbuf, sizeof(unsigned));  
  30.   
  31.     for (;;) {  
  32.         bwr.read_size = sizeof(readbuf);  
  33.         bwr.read_consumed = 0;  
  34.         bwr.read_buffer = (unsigned) readbuf;  
  35.   
  36.         res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  
  37.   
  38.         if (res < 0) {  
  39.             ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));  
  40.             break;  
  41.         }  
  42.   
  43.         res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);  
  44.         if (res == 0) {  
  45.             ALOGE("binder_loop: unexpected reply?!\n");  
  46.             break;  
  47.         }  
  48.         if (res < 0) {  
  49.             ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));  
  50.             break;  
  51.         }  
  52.     }  
  53. }  

在主循环中,Service Manager进程不断的操作Binder驱动,读取到数据后,便调用binder_parse来处理。

  1. int binder_parse(struct binder_state *bs, struct binder_io *bio,  
  2.                  uint32_t *ptr, uint32_t size, binder_handler func)  
  3. {  
  4.     int r = 1;  
  5.     uint32_t *end = ptr + (size / 4);  
  6.   
  7.     while (ptr < end) {  
  8.         uint32_t cmd = *ptr++;  
  9. #if TRACE  
  10.         fprintf(stderr,"%s:\n", cmd_name(cmd));  
  11. #endif  
  12.         switch(cmd) {  
  13.         ……  
  14.         case BR_TRANSACTION: {  
  15.             struct binder_txn *txn = (void *) ptr;  
  16.             if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {  
  17.                 ALOGE("parse: txn too small!\n");  
  18.                 return -1;  
  19.             }  
  20.             binder_dump_txn(txn);  
  21.             if (func) {  
  22.                 unsigned rdata[256/4];  
  23.                 struct binder_io msg;  
  24.                 struct binder_io reply;  
  25.                 int res;  
  26.   
  27.                 bio_init(&reply, rdata, sizeof(rdata), 4);  
  28.                 bio_init_from_txn(&msg, txn);  
  29.                 res = func(bs, txn, &msg, &reply);  
  30.   
  31.                 // 将结果写回Binder驱动  
  32.                 binder_send_reply(bs, &reply, txn->data, res);  
  33.             }  
  34.             ptr += sizeof(*txn) / sizeof(uint32_t);  
  35.             break;  
  36.         }  
  37.         ……  
  38.         default:  
  39.             ALOGE("parse: OOPS %d\n", cmd);  
  40.             return -1;  
  41.         }  
  42.     }  
  43.   
  44.     return r;  
  45. }  

这里的func就是main里面的svcmgr,svcmgr函数用来处理各种命令,包括add_service和get_service等,处理完后,调用binder_send_reply将reply写回binder驱动,从而返回给其客户端进程。我们来看看svcmgr的实现。

  1. int svcmgr_handler(struct binder_state *bs,  
  2.                    struct binder_txn *txn,  
  3.                    struct binder_io *msg,  
  4.                    struct binder_io *reply)  
  5. {  
  6.     struct svcinfo *si;  
  7.     uint16_t *s;  
  8.     unsigned len;  
  9.     void *ptr;  
  10.     uint32_t strict_policy;  
  11.     int allow_isolated;  
  12.   
  13. //    ALOGI("target=%p code=%d pid=%d uid=%d\n",  
  14. //         txn->target, txn->code, txn->sender_pid, txn->sender_euid);  
  15.   
  16.     if (txn->target != svcmgr_handle)  
  17.         return -1;  
  18.   
  19.     // Equivalent to Parcel::enforceInterface(), reading the RPC  
  20.     // header with the strict mode policy mask and the interface name.  
  21.     // Note that we ignore the strict_policy and don't propagate it  
  22.     // further (since we do no outbound RPCs anyway).  
  23.     strict_policy = bio_get_uint32(msg);  
  24.     s = bio_get_string16(msg, &len);  
  25.     if ((len != (sizeof(svcmgr_id) / 2)) ||  
  26.         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  
  27.         fprintf(stderr,"invalid id %s\n", str8(s));  
  28.         return -1;  
  29.     }  
  30.   
  31.     switch(txn->code) {  
  32.     case SVC_MGR_GET_SERVICE:  
  33.     case SVC_MGR_CHECK_SERVICE:  
  34.         s = bio_get_string16(msg, &len);  
  35.         ptr = do_find_service(bs, s, len, txn->sender_euid);  
  36.         if (!ptr)  
  37.             break;  
  38.         bio_put_ref(reply, ptr);  
  39.         return 0;  
  40.   
  41.     case SVC_MGR_ADD_SERVICE:  
  42.         s = bio_get_string16(msg, &len);  
  43.         ptr = bio_get_ref(msg);  
  44.         allow_isolated = bio_get_uint32(msg) ? 1 : 0;  
  45.         if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))  
  46.             return -1;  
  47.         break;  
  48.   
  49.     case SVC_MGR_LIST_SERVICES: {  
  50.         unsigned n = bio_get_uint32(msg);  
  51.   
  52.         si = svclist;  
  53.         while ((n-- > 0) && si)  
  54.             si = si->next;  
  55.         if (si) {  
  56.             bio_put_string16(reply, si->name);  
  57.             return 0;  
  58.         }  
  59.         return -1;  
  60.     }  
  61.     default:  
  62.         ALOGE("unknown code %d\n", txn->code);  
  63.         return -1;  
  64.     }  
  65.   
  66.     bio_put_uint32(reply, 0);  
  67.     return 0;  
  68. }  

是的,我们看到了SVC_MGR_CHECK_SERVICE,SVC_MGR_ADD_SERVICE等命令都最终在这里得到了妥善的处理。

OK,到这里,获取Service的整个流程就完了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值