Android IPC机制Binder解析

来源:互联网 发布:网络转232 编辑:程序博客网 时间:2024/04/30 02:07

花了一个上午的时间把这篇文章翻译完,确实写的很透彻,但美中不足的地方是没有插图,不能直观的了解Binder机制,说实话我自己对binder也理解的很浅显,特别是到binder kernel driver哪块,还要等我先学习linux驱动再来看一遍吧,等以后看懂了再自己绘图应该更有助于理解。

------------------------------------------------------------------------荤勾线-----------------------------------------------------------------------------------------------------

       我将利用IAudioFlinger::setMode这个API作为一个简单的场景,来展示Android IPC系统是如何工作的,AudioFlinger是多媒体服务系统中的一个服务。

 

       运行Service Manager

       service_manager 是为其它进程提供“服务”管理的“服务”。所以,它必须比于其它任何服务先运行。

[cpp] view plaincopy
  1. int main(int argc, char **argv)  
  2. {  
  3.      struct binder_state *bs;  
  4.      void *svcmgr = BINDER_SERVICE_MANAGER;  
  5.      bs = binder_open(128*1024);  
  6.      if (binder_become_context_manager(bs)) {  
  7.            LOGE("cannot become context manager (%s)/n", strerror(errno));  
  8.            return -1;  
  9.      }  
  10.      svcmgr_handle = svcmgr;  
  11.      binder_loop(bs, svcmgr_handler);  
  12.      return 0;  
  13. }  
 

       首先打开“/dev/binder”驱动,且调用BINDER_SET_CONTEXT_MGR这个ioctl,让内核驱动知道该设备是作为管理者(manager)的角色。然后进入一个循环,等待来自其它进程的数据。

[cpp] view plaincopy
  1. void binder_loop(struct binder_state *bs, binder_handler func)  
  2. {  
  3.      int res;  
  4.      struct binder_write_read bwr;  
  5.      unsigned readbuf[32];  
  6.      bwr.write_size = 0;  
  7.      bwr.write_consumed = 0;  
  8.      bwr.write_buffer = 0;  
  9.      readbuf[0] = BC_ENTER_LOOPER;  
  10.      binder_write(bs, readbuf, sizeof(unsigned));  
  11.      for (;;) {  
  12.            bwr.read_size = sizeof(readbuf);  
  13.            bwr.read_consumed = 0;  
  14.            bwr.read_buffer = (unsigned) readbuf;  
  15.     res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  
  16.     if (res < 0) {  
  17.           LOGE("binder_loop: ioctl failed (%s)/n", strerror(errno));  
  18.           break;  
  19.     }  
  20.     res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);  
  21.     if (res == 0) {  
  22.           LOGE("binder_loop: unexpected reply?!/n");  
  23.           break;  
  24.     }  
  25.     if (res < 0) {  
  26.           LOGE("binder_loop: io error %d %s/n", res, strerror(errno));  
  27.           break;  
  28.     }  
  29.   }  
  30. }  
 

        注意BINDER_SERVICE_MANAGER.

[cpp] view plaincopy
  1. /* the one magic object */  
  2. #define BINDER_SERVICE_MANAGER ((void*) 0)  
 
        BINDER_SERVICE_MANAGER是向service_manager注册的句柄(handle),其它进程必须通过它来跟service_manager通信。
        获取IserviceManager
        得到IServiceManager实例的唯一方法是调用IServiceManager.cpp实现的defaultServiceManager接口。
[cpp] view plaincopy
  1. sp<IServiceManager> defaultServiceManager()  
  2. {  
  3.     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;  
  4.     {  
  5.          AutoMutex _l(gDefaultServiceManagerLock);  
  6.          if (gDefaultServiceManager == NULL) {  
  7.               gDefaultServiceManager = interface_cast<IServiceManager>(  
  8.                    ProcessState::self()->getContextObject(NULL));  
  9.          }  
  10.     }  
  11.     return gDefaultServiceManager;  
  12. }  
 
        gDefaultServiceManager在libutil内有定义,所以使用到该对象的程序都要包含该头文件。gDefaultServiceManager初始值为NULL,因此第一次运行时,会通过调用ProcessState::self()获得ProcessState实例。每个进程只能有一个这样的实例。ProcessState会打开“/dev/binder”驱动提供给IPCThreadState使用。
[cpp] view plaincopy
  1. ProcessState::ProcessState()  
  2.     : mDriverFD(open_driver())  
 
         现在我们有了一个ProcessState实例,再来看看getContextObject。
[cpp] view plaincopy
  1. sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)  
  2. {  
  3.     if (supportsProcesses()) {  
  4.           return getStrongProxyForHandle(0);  
  5.     } else {  
  6.           return getContextObject(String16("default"), caller);  
  7.     }  
  8. }  
 
         我们的板子支持binder驱动,所以进入getStrongProxyForHandle。(Handle 0为service manager保留,后续会解释原因。)
[cpp] view plaincopy
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)  
  2. {  
  3.     sp<IBinder> result;  
  4.     AutoMutex _l(mLock);  
  5.     handle_entry* e = lookupHandleLocked(handle);  
  6.     if (e != NULL) {  
  7.           // We need to create a new BpBinder if there isn't currently one, OR we  
  8.           // are unable to acquire a weak reference on this current one. See comment  
  9.           // in getWeakProxyForHandle() for more info about this.  
  10.           IBinder* b = e->binder;  
  11.           if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  12.                 b = new BpBinder(handle);  
  13.                 e->binder = b;  
  14.                 if (b) e->refs = b->getWeakRefs();  
  15.                 result = b;  
  16.           } else {  
  17.                 // This little bit of nastyness is to allow us to add a primary  
  18.                 // reference to the remote proxy when this team doesn't have one  
  19.                 // but another team is sending the handle to us.  
  20.                 result.force_set(b);  
  21.                 e->refs->decWeak(this);  
  22.           }  
  23.     }  
  24.   return result;  
  25. }  
 
        初次b将会是NULL,所以这段代码会new 一个BpBinder实例。BpBinder是一个远程binder对象的代理类。
[cpp] view plaincopy
  1. BpBinder::BpBinder(int32_t handle)  
  2.     : mHandle(handle)  
  3.     , mAlive(1)  
  4.     , mObitsSent(0)  
  5.     , mObituaries(NULL)  
  6. {  
  7.     LOGV("Creating BpBinder %p handle %d/n"this, mHandle);  
  8.     extendObjectLifetime(OBJECT_LIFETIME_WEAK);  
  9.     IPCThreadState::self()->incWeakHandle(handle);  
  10. }  
 
        IPCThreadState::incWeakHandle将添加一个BC_INCREFS的命令到输出buffer
[cpp] view plaincopy
  1. void IPCThreadState::incWeakHandle(int32_t handle)  
  2. {  
  3.      LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)/n", handle);  
  4.      mOut.writeInt32(BC_INCREFS);  
  5.      mOut.writeInt32(handle);  
  6. }  
 
        现在getContextObject返回了一个BpBinder的实例,它将通过interface_cast转换为IServiceManager.interface_cast在IInterface.h有定义,展开如下:
[cpp] view plaincopy
  1. inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)  
  2. {  
  3.      return IServiceManager::asInterface(obj);  
  4. }  
 
现在我们来看看IServiceManager的定义
[cpp] view plaincopy
  1. class IServiceManager : public IInterface  
  2. {  
  3. public:  
  4.      DECLARE_META_INTERFACE(ServiceManager);  
  5.      /** 
  6.        * Retrieve an existing service, blocking for a few seconds 
  7.        * if it doesn't yet exist. 
  8.        */  
  9.      virtual sp<IBinder>             getService( const String16& name) const = 0;  
  10.      /** 
  11.        * Retrieve an existing service, non-blocking. 
  12.        */  
  13.      virtual sp<IBinder>             checkService( const String16& name) const = 0;  
  14.    /** 
  15.     * Register a service. 
  16.     */  
  17.    virtual status_t                addService( const String16& name,  
  18.                                                        const sp<IBinder>& service) = 0;  
  19.    /** 
  20.     * Return list of all existing services. 
  21.     */  
  22.    virtual Vector<String16>        listServices() = 0;  
  23.    enum {  
  24.         GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,  
  25.         CHECK_SERVICE_TRANSACTION,  
  26.         ADD_SERVICE_TRANSACTION,  
  27.         LIST_SERVICES_TRANSACTION,  
  28.    };  
  29. };  
 
DECLARE_META_INTERFACE是在IInterface.h中定义的一个宏,展开如下:
[cpp] view plaincopy
  1. static const String16 descriptor;  
  2. static sp<IServiceManager> asInterface(const sp<IBinder>& obj);  
  3. virtual String16 getInterfaceDescriptor() const;  
 
如你所见,DECLARE_META_INTERFACE宏生命了两个函数,这两个函数将在IServiceManager.cpp中被实现
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
代码展开如下:
[cpp] view plaincopy
  1. const String16 IServiceManager::descriptor(NAME);  
  2. String16 IServiceManager::getInterfaceDescriptor() const {  
  3.      return IServiceManager::descriptor;  
  4. }  
  5. sp<IServiceManager> IServiceManager::asInterface(const sp<IBinder>& obj)  
  6. {  
  7.      sp<IServiceManager> intr;  
  8.      if (obj != NULL) {  
  9.            intr = static_cast<IServiceManager*>(  
  10.                  obj->queryLocalInterface(  
  11.                            IServiceManager::descriptor).get());  
  12.            if (intr == NULL) {  
  13.                  intr = new BpServiceManager(obj);  
  14.            }  
  15.      }  
  16.      return intr;  
  17. }  
 
所以IServiceManager::asInterface最终会new一个BpServiceManager实例,并且返回给用户。BpServiceManager作为远程BnServiceManager的代理。任何在IServiceManager操作现在实际上是调用BpServiceManager相应的虚函数。
摘要:
这个部分给出了如何获取远程对象的代理对象,加入你想实现你自己的服务IFunnyTest,你必须完成下面的步骤:
1、将DECLARE_META_INTERFACE(FunnyTest)宏写进你的接口头文件(interface header file)。
2、讲IMPLEMENT_META_INTERFACE(Funnytest, “your unique name”)宏放进你的接口源文件(interface source file)。
3、实现你自己的BpFunnyTest类。
触发AudioFlinger服务
media_server系统讲会启动AudioFlinger服务,代码如下:
[cpp] view plaincopy
  1. int main(int argc, char** argv)  
  2. {  
  3.      sp<ProcessState> proc(ProcessState::self());  
  4.      sp<IServiceManager> sm = defaultServiceManager();  
  5.      LOGI("ServiceManager: %p", sm.get());  
  6.      AudioFlinger::instantiate();  
  7.      MediaPlayerService::instantiate();  
  8.      CameraService::instantiate();  
  9.      ProcessState::self()->startThreadPool();  
  10.      IPCThreadState::self()->joinThreadPool();  
  11. }  
 
AudioFlinger将会调用ServiceManager::addService,这是个远程调用(RPC)。
[cpp] view plaincopy
  1. void AudioFlinger::instantiate() {  
  2.      defaultServiceManager()->addService(  
  3.                String16("media.audio_flinger"), new AudioFlinger());  
  4. }  
 
AudioFlinger继承字BnAudioFlinger,BnAudioFlinger是BnInterface的模板(template);
[cpp] view plaincopy
  1. class BnAudioFlinger : public BnInterface<IAudioFlinger>  
  2. {  
  3. public:  
  4.      virtual status_t   onTransact( uint32_t code,  
  5.                                            const Parcel& data,  
  6.                                            Parcel* reply,  
  7.                                            uint32_t flags = 0);  
  8. };  
 
BnInterface继承自BBinder.
[cpp] view plaincopy
  1. template<typename INTERFACE>class BnInterface : public INTERFACE, public BBinder  
  2. {  
  3. public:  
  4.      virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);  
  5.      virtual String16             getInterfaceDescriptor() const;  
  6. protected:  
  7.      virtual IBinder*             onAsBinder();  
  8. };  
  9. template<typename INTERFACE>  
  10. IBinder* BnInterface<INTERFACE>::onAsBinder()  
  11. {  
  12.      return this;  
  13. }  
 
根据BnInterface的实现,我们知道传给IServiceManager::addService的参数实际上是一个AudioFlinger实例的地址,BBinder继承自IBinder,它的transact函数将会调用虚函数onTransact。
[cpp] view plaincopy
  1. status_t BBinder::transact(  
  2.      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.      data.setDataPosition(0);  
  5.      status_t err = NO_ERROR;  
  6.      switch (code) {  
  7.            case PING_TRANSACTION:  
  8.                 reply->writeInt32(pingBinder());  
  9.                 break;  
  10.            default:  
  11.                 err = onTransact(code, data, reply, flags);  
  12.                 break;  
  13.      }  
  14.      if (reply != NULL) {  
  15.            reply->setDataPosition(0);  
  16.      }  
  17.      return err;  
  18. }  
 
这里面最重要的函数就是onTransact。BnAudioFlinger会实现这个虚函数,在这里,我们只需要专注于SET_MODE这个分支。
[cpp] view plaincopy
  1. status_t BnAudioFlinger::onTransact(  
  2.      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.      switch(code) {  
  5. case SET_MODE: {  
  6.      CHECK_INTERFACE(IAudioFlinger, data, reply);  
  7.      int mode = data.readInt32();  
  8.      reply->writeInt32( setMode(mode) );  
  9.      return NO_ERROR;  
  10. break;  
 
media_server将会通过IPCThreadState::joinThreadPool进入一个循环,就向service_manager一样,它会在talkWithDriver里面等待来自其它进程的数据。
[cpp] view plaincopy
  1. void IPCThreadState::joinThreadPool(bool isMain)  
  2. {  
  3.      mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  4.      status_t result;  
  5.      do {  
  6.           int32_t cmd;  
  7.           result = talkWithDriver();  
  8.           if (result >= NO_ERROR) {  
  9.                 size_t IN = mIn.dataAvail();  
  10.                 if (IN < sizeof(int32_t)) continue;  
  11.                 cmd = mIn.readInt32();  
  12.                 result = executeCommand(cmd);  
  13.           }  
  14.           // Let this thread exit the thread pool if it is no longer  
  15.           // needed and it is not the main process thread.  
  16.           if(result == TIMED_OUT && !isMain) {  
  17.                 break;  
  18.           }  
  19.      } while (result != -ECONNREFUSED && result != -EBADF);  
  20.      mOut.writeInt32(BC_EXIT_LOOPER);  
  21.      talkWithDriver(false);  
  22. }  
 
假如你想实现自己的IFunnyTest服务,你必须做到洗面几点:
1、实现你自己的BnFunnyTest类
2、在你的服务运行的进程里,调用IPCThreadState::joinThreadPool开始binder循环。
远程调用(RPC Call)IServiceManager::addService
我们调用IServiceManager::addService,其实是调用BpServiceManager::addService。
[cpp] view plaincopy
  1. virtual status_t addService(const String16& name, const sp<IBinder>& service){  
  2.   Parcel data, reply;  
  3.   data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  4.   data.writeString16(name);  
  5.   data.writeStrongBinder(service);  
  6.   status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  7.   return err == NO_ERROR ? reply.readInt32() : err;  
  8. }  
 
Parcel很简单,我们把它想象成一个连续的buffer。这里要注意,service这个参数只想BBinder对象(AudioFlinger继承自Bn)
[cpp] view plaincopy
  1. status_t Parcel::writeStrongBinder(const sp<IBinder>& val)  
  2. {  
  3.      return flatten_binder(ProcessState::self(), val, this);  
  4. }  
 
flatten_binder将会触发一个Binber指令。因为BBinder是一个本地(local)的binder对象,所以我们的代码分支将会标识成红色
[cpp] view plaincopy
  1. status_t flatten_binder(const sp<ProcessState>& proc,  
  2.      const sp<IBinder>& binder, Parcel* out)  
  3. {  
  4.      flat_binder_object obj;  
  5.      obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;  
  6.      if (binder != NULL) {  
  7.            IBinder *local = binder->localBinder();  
  8.            if (!local) {  
  9.                  BpBinder *proxy = binder->remoteBinder();  
  10.                  if (proxy == NULL) {  
  11.                        LOGE("null proxy");  
  12.                  }  
  13.                  const int32_t handle = proxy ? proxy->handle() : 0;  
  14.                  obj.type = BINDER_TYPE_HANDLE;  
  15.                  obj.handle = handle;  
  16.                  obj.cookie = NULL;  
  17.            } else {  
  18.                  obj.type = BINDER_TYPE_BINDER;  
  19.                  obj.binder = local->getWeakRefs();  
  20.                  obj.cookie = local;  
  21.            }  
  22.      }  
  23.      return finish_flatten_binder(binder, obj, out);  
  24. }  
 
注意这几行红色的代码,local的地址放入(稍候会用到)。等到addService这个远程调用(RPC)用到的数据包(packet)打包好后,BpServiceManager::addService将会调用BpBinder的transact方法。
[cpp] view plaincopy
  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.      return DEAD_OBJECT;  
  12. }  
 
BpBinder调用IPCThreadState::transact开始将binder对象传送给对应的句柄(mHandler),在这里,mHandler为0。(也就是传送给service manager这个服务)。
[cpp] view plaincopy
  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.      if (err == NO_ERROR) {  
  8.             LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),  
  9.                   (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");  
  10.             err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  11.      }  
  12.      if (err != NO_ERROR) {  
  13.             if (reply) reply->setError(err);  
  14.             return (mLastError = err);  
  15.      }  
  16.      if ((flags & TF_ONE_WAY) == 0) {  
  17.             if (reply) {  
  18.                   err = waitForResponse(reply);  
  19.             } else {  
  20.                   Parcel fakeReply;  
  21.                   err = waitForResponse(&fakeReply);  
  22.             }  
  23.      } else {  
  24.             err = waitForResponse(NULL, NULL);  
  25.      }  
  26.   return err;  
  27. }  
 
IPCThreadState::transact开始会调用writeTransactionData为binder的内核驱动构造一个传输数据的结构体,注意以下代码,这对binder内核驱动区分传输目标(transaction target)非常重要。
[cpp] view plaincopy
  1. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
  2.      int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)  
  3. {  
  4.      binder_transaction_data tr;  
  5.      tr.target.handle = handle;  
  6.      tr.code = code;  
  7.      tr.flags = binderFlags;  
  8.      const status_t err = data.errorCheck();  
  9.      if (err == NO_ERROR) {  
  10.            tr.data_size = data.ipcDataSize();  
  11.            tr.data.ptr.buffer = data.ipcData();  
  12.            tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  13.            tr.data.ptr.offsets = data.ipcObjects();  
  14.      } else if (statusBuffer) {  
  15.            tr.flags |= TF_STATUS_CODE;  
  16.            *statusBuffer = err;  
  17.            tr.data_size = sizeof(status_t);  
  18.            tr.data.ptr.buffer = statusBuffer;  
  19.            tr.offsets_size = 0;  
  20.            tr.data.ptr.offsets = NULL;  
  21.      } else {  
  22.            return (mLastError = err);  
  23.      }  
  24.      mOut.writeInt32(cmd);  
  25.      mOut.write(&tr, sizeof(tr));  
  26.      return NO_ERROR;  
  27. }  
 
然后waitForResponse会调用talkWithDriver,ioctl设置为BINDER_WRITE_READ。
[cpp] view plaincopy
  1. #if defined(HAVE_ANDROID_OS)  
  2.           if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  3.                 err = NO_ERROR;  
  4.           else  
  5.                 err = -errno;  
  6. #else  
 
现在,数据已经传送给了binder内核驱动。
摘要:
代理对象会触发一个需要数据包的RPC,然后调用BINDER_WRITE_READ将数据包传给binder内核驱动。这个数据包是一个格式化的包,对与RPC,它使用的包类型是BC_TRANSACTION
假定你想实现你自己的IfunnyTest,你必须完成下面几点:
在你的服务运行的进程里面,调用IServiceManager::addService想service_manager注册你的服务
在Binber内核驱动里面的传输
当任何进程打开“/dev/binder”驱动的时候,一个对应的binder_proc结构将会传递给binder_open。
[cpp] view plaincopy
  1. static int binder_open(struct inode *nodp, struct file *filp)  
  2. {  
  3.       struct binder_proc *proc;  
  4.       proc = kzalloc(sizeof(*proc), GFP_KERNEL);  
  5.       if (proc == NULL)  
  6.             return -ENOMEM;  
  7.       get_task_struct(current);  
  8.       proc->tsk = current;  
  9.       INIT_LIST_HEAD(&proc->todo);  
  10.       init_waitqueue_head(&proc->wait);  
  11.       proc->default_priority = task_nice(current);  
  12.       mutex_lock(&binder_lock);  
  13.       binder_stats.obj_created[BINDER_STAT_PROC]++;  
  14.       hlist_add_head(&proc->proc_node, &binder_procs);  
  15.       proc->pid = current->group_leader->pid;  
  16.       INIT_LIST_HEAD(&proc->delivered_death);  
  17.       filp->private_data = proc;  
  18.       mutex_unlock(&binder_lock);  
  19.       if (binder_proc_dir_entry_proc) {  
  20.             char strbuf[11];  
  21.             snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);  
  22.             create_proc_read_entry(strbuf,            S_IRUGO, binder_proc_dir_entry_proc,  
  23. binder_read_proc_proc, proc);  
  24.       }  
  25.       return 0;  
  26. }  
 
所以,当任何ioctl到来的时候,驱动都知道他的进程信息,传输数据是通过BINDER_WRITE_READ的ioctl来传送的。
[cpp] view plaincopy
  1. case BINDER_WRITE_READ: {  
  2.           struct binder_write_read bwr;  
  3.           if (size != sizeof(struct binder_write_read)) {  
  4.                 ret = -EINVAL;  
  5.                 goto err;  
  6.           }  
  7.           if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {  
  8.                 ret = -EFAULT;  
  9.                 goto err;  
  10.           }  
  11.           if (bwr.write_size > 0) {  
  12.                 ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer,  
  13. bwr.write_size, &bwr.write_consumed);  
  14.                 if (ret < 0) {  
  15.                        bwr.read_consumed = 0;  
  16.                        if (copy_to_user(ubuf, &bwr, sizeof(bwr)))  
  17.                              ret = -EFAULT;  
  18.                        goto err;  
  19.                 }  
  20.           }  
  21.           if (bwr.read_size > 0) {  
  22.                 ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer,  
  23. bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);  
  24.                 if (!list_empty(&proc->todo))  
  25.                        wake_up_interruptible(&proc->wait);  
  26.                 if (ret < 0) {  
  27.                        if (copy_to_user(ubuf, &bwr, sizeof(bwr)))  
  28.                              ret = -EFAULT;  
  29.                        goto err;  
  30.                 }  
  31.           }  
  32.           if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {  
  33.                 ret = -EFAULT;  
  34.                 goto err;  
  35.           }  
  36.           break;  
  37.      }  
 
驱动首先进行写操作,我们先看看binder_thread_write。binder_thread_write的核心,是一个循环,它将指令打包写到buffer里面,然后执行响应的指令。
[cpp] view plaincopy
  1. uint32_t cmd;  
  2. void __user *ptr = buffer + *consumed;  
  3. void __user *end = buffer + size;  
  4.      while (ptr < end && thread->return_error == BR_OK) {  
  5.          if (get_user(cmd, (uint32_t __user *)ptr))  
  6.                return -EFAULT;  
  7.          ptr += sizeof(uint32_t);  
  8.          if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {  
  9.                binder_stats.bc[_IOC_NR(cmd)]++;  
  10.                proc->stats.bc[_IOC_NR(cmd)]++;  
  11.                thread->stats.bc[_IOC_NR(cmd)]++;  
  12.          }  
  13.          switch (cmd) {  
  14.          case ***:  
  15.          default:  
  16.                printk(KERN_ERR "binder: %d:%d unknown command %d/n", proc->pid,  
  17. thread->pid, cmd);  
  18.                return -EINVAL;  
  19.          }  
  20.          *consumed = ptr - buffer;  
  21.      }  
 
我们看看其中的两个指令,一个是BC_INCREFS.
[cpp] view plaincopy
  1. case BC_INCREFS:  
  2. case BC_ACQUIRE:  
  3. case BC_RELEASE:  
  4. case BC_DECREFS: {  
  5.      uint32_t target;  
  6.      struct binder_ref *ref;  
  7.      const char *debug_string;  
  8.      if (get_user(target, (uint32_t __user *)ptr))  
  9.            return -EFAULT;  
  10.      ptr += sizeof(uint32_t);  
  11.      if (target == 0 && binder_context_mgr_node &&  
  12.            (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {  
  13.            ref = binder_get_ref_for_node(proc,  
  14.                          binder_context_mgr_node);  
  15.      } else  
  16.            ref = binder_get_ref(proc, target);  
  17.      if (ref == NULL) {  
  18.            binder_user_error("binder: %d:%d refcou"  
  19.                  "nt change on invalid ref %d/n",  
  20.                  proc->pid, thread->pid, target);  
  21.            break;  
  22.      }  
  23. switch (cmd) {  
  24. case BC_INCREFS:  
  25.      debug_string = "IncRefs";  
  26.      binder_inc_ref(ref, 0, NULL);  
  27.      break;  
  28. }  
  29. break;  
 
记住,我们上面提到,在这里,我们的目标(target)是0,当system_manager调用BINDER_SET_CONTEXT_MGR这个ioctl的时候,binder_context_mgr_node代表0。所以这里仅仅是将binder_context_mgr_node节点的弱应用(weak reference)增加1.。
binder_context_mgr_node = binder_new_node(proc, NULL);
另一个指令是BC_TRANSACTION.
[cpp] view plaincopy
  1. case BC_TRANSACTION:  
  2. case BC_REPLY: {  
  3.      struct binder_transaction_data tr;  
  4.      if (copy_from_user(&tr, ptr, sizeof(tr)))  
  5.            return -EFAULT;  
  6.      ptr += sizeof(tr);  
  7.      binder_transaction(proc, thread, &tr, cmd == BC_REPLY);  
  8.      break;  
  9. }  
 
假如数据包里面包含BINDER_TYPE_BINDER这个flattened对象的话,binder_transaction将会创建一个信的binder节点。
[cpp] view plaincopy
  1. fp = (struct flat_binder_object *)(t->buffer->data + *offp);  
  2. switch (fp->type) {  
  3. case BINDER_TYPE_BINDER:  
  4. case BINDER_TYPE_WEAK_BINDER: {  
  5.      struct binder_ref *ref;  
  6.      struct binder_node *node = binder_get_node(proc, fp->binder);  
  7.      if (node == NULL) {  
  8.            node = binder_new_node(proc, fp->binder);  
  9.            if (node == NULL) {  
  10.                  return_error = BR_FAILED_REPLY;  
  11.                  goto err_binder_new_node_failed;  
  12.            }  
  13.            node->cookie = fp->cookie;  
  14.      }  
  15.      ref = binder_get_ref_for_node(target_proc, node);  
  16.      if (ref == NULL) {  
  17.            return_error = BR_FAILED_REPLY;  
  18.            goto err_binder_get_ref_for_node_failed;  
  19.      }  
  20.      if (fp->type == BINDER_TYPE_BINDER)  
  21.            fp->type = BINDER_TYPE_HANDLE;  
  22.      else  
  23.            fp->type = BINDER_TYPE_WEAK_HANDLE;  
  24.      fp->handle = ref->desc;  
  25.      binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);  
  26.      if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)  
  27.            printk(KERN_INFO "           node %d u%p -> ref %d desc %d/n",  
  28.                    node->debug_id, node->ptr, ref->debug_id, ref->desc);  
  29. break;  
 
binder_transaction会知道目标是句柄(handle)0,所以运行下列分支,找到target_node, target_proc和target_thread
[cpp] view plaincopy
  1. else {  
  2.       target_node = binder_context_mgr_node;  
  3.       if (target_node == NULL) {  
  4.             return_error = BR_DEAD_REPLY;  
  5.             goto err_no_context_mgr_node;  
  6.       }  
  7. }  
  8. e->to_node = target_node->debug_id;  
  9. target_proc = target_node->proc;  
  10. if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {  
  11.       struct binder_transaction *tmp;  
  12.       tmp = thread->transaction_stack;  
  13.       while (tmp) {  
  14.             if (tmp->from && tmp->from->proc == target_proc)  
  15.                   target_thread = tmp->from;  
  16.             tmp = tmp->from_parent;  
  17.       }  
  18. }  
 
最终,binder_transaction会讲请求放入列表,唤醒等待binder_thread_read里面的线程。
[cpp] view plaincopy
  1. t->work.type = BINDER_WORK_TRANSACTION;  
  2. list_add_tail(&t->work.entry, target_list);  
  3. tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;  
  4. list_add_tail(&tcomplete->entry, &thread->todo);  
  5. if (target_wait)  
  6.       wake_up_interruptible(target_wait);  
 
现在我们来看看binder_thread_read。当service_manager跑起来后,它会在这里等待一直到有请求到来。
[cpp] view plaincopy
  1. ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc,thread));  
 
因为之前media_server进程的写请求已经把它唤醒了,所以继续执行。下面的代码是从media_server的写buffer拷贝到system_manager的读buffer
[cpp] view plaincopy
  1. tr.data_size = t->buffer->data_size;  
  2. tr.offsets_size = t->buffer->offsets_size;  
  3. tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset);  
  4. tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));  
  5. if (put_user(cmd, (uint32_t __user *)ptr))  
  6.       return -EFAULT;  
  7. ptr += sizeof(uint32_t);  
  8. if (copy_to_user(ptr, &tr, sizeof(tr)))  
  9.       return -EFAULT;  
  10. ptr += sizeof(tr);  
 
摘要:
这部分展示了RPC的客户端和服务端的数据流向。
Service Manager 处理 Add Service请求
直到现在,service_manager已经从madia_server的BR_TRANSACTION数据包,然后调用binder_paser处理这个数据包。
[cpp] view plaincopy
  1. case BR_TRANSACTION: {  
  2.      if (func) {  
  3.            unsigned rdata[256/4];  
  4.            struct binder_io msg;  
  5.            struct binder_io reply;  
  6.            int res;  
  7.            bio_init(&reply, rdata, sizeof(rdata), 4);  
  8.            bio_init_from_txn(&msg, txn);  
  9.            res = func(bs, txn, &msg, &reply);  
  10.            binder_send_reply(bs, &reply, txn->data, res);  
  11.      }  
  12.      ptr += sizeof(*txn) / sizeof(uint32_t);  
  13.      break;  
  14. }  
 
binder_parser调用svcmgr_handler解析BR_TRANSACTION包,跟BpServerManager进程相反。这里的结构体binder_txn实际上跟binder_transaction_data相同。在这里,传输码(transaction code)是SVC_MGR_ADD_SERVICE.
[cpp] view plaincopy
  1. binder_parser will call svcmgr_handler to parse BR_TRANSACTION packet, which is the reverse  
  2. process of BpServerManager. Here structure binder_txn actually is the same with structure  
  3. binder_transaction_data. In our scenario, the transaction code is SVC_MGR_ADD_SERVICE.  
  4. int svcmgr_handler(struct binder_state *bs,  
  5.                          struct binder_txn *txn,  
  6.                          struct binder_io *msg,  
  7.                        struct binder_io *reply)  
  8. {  
  9.   struct svcinfo *si;  
  10.   uint16_t *s;  
  11.   unsigned len;  
  12.   void *ptr;  
  13.   if (txn->target != svcmgr_handle)  
  14.         return -1;  
  15.   s = bio_get_string16(msg, &len);  
  16.   if ((len != (sizeof(svcmgr_id) / 2)) ||  
  17.         memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  
  18.         fprintf(stderr,"invalid id %s/n", str8(s));  
  19.         return -1;  
  20.   }  
  21.   switch(txn->code) {  
  22.   case SVC_MGR_ADD_SERVICE:  
  23.         s = bio_get_string16(msg, &len);  
  24.         ptr = bio_get_ref(msg);  
  25.         if (do_add_service(bs, s, len, ptr, txn->sender_euid))  
  26.               return -1;  
  27.         break;  
 
因此,service_manager知道这个服务即将启动,并且调用bio_get_ref来获取服务的信息。
[cpp] view plaincopy
  1. void *bio_get_ref(struct binder_io *bio)  
  2. {  
  3.      struct binder_object *obj;  
  4.      obj = _bio_get_obj(bio);  
  5.      if (!obj)  
  6.            return 0;  
  7.      if (obj->type == BINDER_TYPE_HANDLE)  
  8.            return obj->pointer;  
  9.      return 0;  
  10. }  
 
bio_get_ref做了flatten_binder完全相反的工作。do_add_service最终通过调用BC_ACQUIRE得到一个对象的强引用,由ptr指向它。
摘要:
这部分展示了服务怎么添加到service manager中去。
假如你想实现你自己的服务IFunnyTest,你必须完成一下步骤:
1、将你的服务名字添加到service_manager的服务列表里去
获取IaudioFlinger
获取service接口的唯一途径是通过调用IServiceManager::getService。比如说,这里的获取AudioSystem的方法是IAudioFlinger.
[cpp] view plaincopy
  1.  / establish binder interface to AudioFlinger service  
  2. const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()  
  3. {  
  4.       Mutex::Autolock _l(gLock);  
  5.       if (gAudioFlinger.get() == 0) {  
  6.            sp<IServiceManager> sm = defaultServiceManager();  
  7.            sp<IBinder> binder;  
  8.            do {  
  9.                 binder = sm->getService(String16("media.audio_flinger"));  
  10.                 if (binder != 0)  
  11.                       break;  
  12.                 LOGW("AudioFlinger not published, waiting...");  
  13.                 usleep(500000); // 0.5 s  
  14.            } while(true);  
  15.            gAudioFlinger = interface_cast<IAudioFlinger>(binder);  
  16.       }  
  17.       LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");  
  18.       return gAudioFlinger;  
  19. }  
  20. IServiceManager::getService会调用BpServiceManager::getService.  
  21. virtual sp<IBinder> getService(const String16& name) const  
  22. {  
  23.      unsigned n;  
  24.      for (n = 0; n < 5; n++){  
  25.            sp<IBinder> svc = checkService(name);  
  26.            if (svc != NULL) return svc;  
  27.            LOGI("Waiting for sevice %s.../n", String8(name).string());  
  28.            sleep(1);  
  29.      }  
  30.      return NULL;  
  31. }  
  32. virtual sp<IBinder> checkService( const String16& name) const  
  33. {  
  34.      Parcel data, reply;  
  35.      data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  36.   data.writeString16(name);  
  37.   remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);  
  38.   return reply.readStrongBinder();  
  39. }  
 

就跟刚才分析的一样,这个调用最终会通过binder内核驱动被service_manager处理。
[cpp] view plaincopy
  1. switch(txn->code) {  
  2. case SVC_MGR_GET_SERVICE:  
  3. case SVC_MGR_CHECK_SERVICE:  
  4.      s = bio_get_string16(msg, &len);  
  5.      ptr = do_find_service(bs, s, len);  
  6.      if (!ptr)  
  7.            break;  
  8.      bio_put_ref(reply, ptr);  
  9.      return 0;  
 
然后service_manager会返回一个先前的句柄(previous handle),这个句柄由media_server设置,实际上就是AudioFlinger实例的地址。然后BpServiceManager::checkService会从remote()->transact调用中返回。然后,就像在IServiceManager中分析的一样,它将创建一个新的BpBinder实例,对应service_manager返回的handle,interface_cast<IAudioFlinger>(binder)最终返回一个BpAudioFlinger实例。
摘要
就想获取IServieManager一样,但是这次需要获取一个service_manager的handle,当然我们的IServiceManager的handle总是为0.

远程调用IAudioFlinger::SetMode
加入我们在AAA进程中调用IAudioFlinger::SetMode,实际上我们调用的是
[cpp] view plaincopy
  1. BpAudioFlinger::setMode.  
  2. virtual status_t setMode(int mode)  
  3. {  
  4.      Parcel data, reply;  
  5.      data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());  
  6.      data.writeInt32(mode);  
  7.      remote()->transact(SET_MODE, data, &reply);  
  8.      return reply.readInt32();  
  9. }  
 
就像分析IServiceManager::addService一样,这个函数将会出发一个数据包,并写入binder驱动内核,等待读应答。唯一的不同点是target handle指向了media_server进程的某些地址。
处理 IAudioFlinger::SetMode
Binder内核驱动最终会唤醒在media_server进程中运行在IPCThreadState::joinThreadPool的读线程,现在我们再来看看这段代码:
[cpp] view plaincopy
  1. oid IPCThreadState::joinThreadPool(bool isMain)  
  2.   
  3.     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  4.     status_t result;  
  5.     do {  
  6.          int32_t cmd;  
  7.          result = talkWithDriver();  
  8.          if (result >= NO_ERROR) {  
  9.                size_t IN = mIn.dataAvail();  
  10.                if (IN < sizeof(int32_t)) continue;  
  11.                cmd = mIn.readInt32();  
  12.                result = executeCommand(cmd);  
  13.          }  
  14.          // Let this thread exit the thread pool if it is no longer  
  15.          // needed and it is not the main process thread.  
  16.          if(result == TIMED_OUT && !isMain) {  
  17.                break;  
  18.          }  
  19.     } while (result != -ECONNREFUSED && result != -EBADF);  
  20.     mOut.writeInt32(BC_EXIT_LOOPER);  
  21.     talkWithDriver(false);  
 
这一次,talkWithDriver讲返回BpServiceManager::setMode生成的数据包,然后executeCommand会处理这些命令,在这里,命令是BR_TRANSACTION.
[cpp] view plaincopy
  1. case BR_TRANSACTION:  
  2.      {  
  3.         binder_transaction_data tr;  
  4.         Parcel reply;  
  5.         if (tr.target.ptr) {  
  6.                sp<BBinder> b((BBinder*)tr.cookie);  
  7.                const status_t error = b->transact(tr.code, buffer, &reply, 0);  
  8.                if (error < NO_ERROR) reply.setError(error);  
  9.         } else {  
  10.                const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);  
  11.             if (error < NO_ERROR) reply.setError(error);  
  12.      }  
  13.      if ((tr.flags & TF_ONE_WAY) == 0) {  
  14.             LOG_ONEWAY("Sending reply to %d!", mCallingPid);  
  15.             sendReply(reply, 0);  
  16.      } else {  
  17.             LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);  
  18.      }  
  19. }  
  20. break;  
 
最重要的两行已经标记为红色,这里获取了从binder内核驱动的地址,并且强制转换为BBinder指针(这个地址当调用IServiceManager::addService时传给了binder内核驱动)。记住,AudioFlinger是派生自Bbinder。这个指针实际上指向的就是我们的AudioFlinger实例。所以写下来的trancat调用最终会调用我们BnAudioFlinger的onTransact这个虚函数。
[cpp] view plaincopy
  1. status_t BnAudioFlinger::onTransact(  
  2.      uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.           case SET_MODE: {  
  5.                CHECK_INTERFACE(IAudioFlinger, data, reply);  
  6.                int mode = data.readInt32();  
  7.                reply->writeInt32( setMode(mode) );  
  8.                return NO_ERROR;  
  9.           } break;  
  10. }  
 
然后将通过调用sendReply将应答写回去。
[cpp] view plaincopy
  1. status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)  
  2. {  
  3.      status_t err;  
  4.      status_t statusBuffer;  
  5.      err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);  
  6.      if (err < NO_ERROR) return err;  
  7.      return waitForResponse(NULL, NULL);  
  8. }  
 
它最终写到binder内核驱动里去,内核驱动最后会唤醒AAA进程的读线程。
摘要
Service_manager<---->service provider<------->service user
     |                                         |                                 | 
     |                                         |                                 |
     |                                         |                                 |
     |                                         |                                 |
     ------------------------>Binder Driver<-----------------
这是Android IPC系统的大致架构,分为四大块。
1、Binder Driver
   这是IPC系统的核心,负责service provider 和service user之间的数据传输
2、service provider
   它提供一些服务,它解析来自binder driver的数据,并且真正执行动作。
3、service_manager
   这是一个特殊的服务。它为其它的服务提供管理服务。
4、service user
   它远程调用service provider,出发一个RPC调用,并将数据传入binder driver
在我们所列举的场景里面,下面列举出了主要的控制流程
1、service_manager首先运行,它想binder driver注册特殊的节点0
2、Media_server 获取特殊节点0的IServiceManager代理对象
3、media_server通过RPC调用IServiceManager::addService添加IAudioFlinger服务,
这个调用的目的节点为0。然后向binder driver发送数据。
4、Binder driver知道数据是给节点0的,然后数据包含了创建新节点的指令,因此它为IAudioFlinger创建另外一个节点(假如为A),表示service_manager.
5、service_manager读取来自binder driver的数据,然后处理IServiceManager::addService的RPC调用
6、另外一个进程P获取特殊节点0的IServiceManager对象
7、P通过RPC调用IServiceManager::getService获取IAudioFlinger服务。这个调用追溯到节点0,它发送据给binder driver
8、Binder driver知道数据是给节点0的,所以它把数据传给service_manager.
9、service_manager读取从binder driver传上来的数据,处理IServiceManager::getService调用,将代表IAudioFlinger服务的节点A发回给binder driver
10、P 通过RPC调用l IAudioFlinger::setMode. 现在这个调用追溯的节点是A.
11、Binder driver知道数据是给节点A的,所以它把数据传给media_server.
12、media_server读取数据,处理IAudioFlinger::setMode调用,将结果发回给binder driver
13、Binder driver讲结果发回给进程P
14、P从binder driver读取数据,这样最终的结果就得到了
0 0
原创粉丝点击