权力的游戏里经典台词:Android-IPC-Binder(1)

来源:百度文库 编辑:偶看新闻 时间:2024/05/01 17:41:19

本文以IAudioFlinger::setMode函数为例,展示Android IPC是如何工作的。AudioFlinger是Android多媒体服务器程序中一个服务。

Service Manager Run

service_manager为其他进程提供了服务管理的服务,必须在所有服务运行之前启动。

view plaincopy to clipboard?

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

它首先打开了/dev/binder驱动,然后调用binder_become_context_manager()函数(其本质是调用ioctl设置BINDER_SET_CONTEXT_MGR)来通知binder内核驱动它是管理者。然后,进入循环,等待其他进程传入的数据。

view plaincopy to clipboard?

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

注意BINDER_SERVICE_MANAGER的定义

/* the one magic object */

#define BINDER_SERVICE_MANAGER ((void*) 0)

BINDER_SERVICE_MANAGER是service_manager注册的handle。其他进程必须使用它来与service_manager进行对话。

Get IserviceManager

只能通过调用defaultServiceManager()函数来获取一个IserviceManager实例。该函数在IServiceManager.cpp中实现。

view plaincopy to clipboard?

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

gDefaultServiceManager在libutil中定义,因此任何程序或库使用了libutil库都会有该符号,它在一个进程中唯一。起初gDefaultServiceManager为NULL,于是先调用ProcessState::self()获取一个ProcessState实例。一个进程只有一个ProcessState实例。该ProcessState会打开/dev/binder驱动供IPCThreadState使用。

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/ ProcessState.cpp   
  2. ProcessState::ProcessState()  
  3.     : mDriverFD(open_driver())  
 

现在,我们有了一个ProcessState实例,让我们看看getContextObject()函数都做了什么。

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/ProcessState.cpp   
  2. sp ProcessState::getContextObject(const sp& caller)  
  3. {  
  4.   if (supportsProcesses()) {  
  5.     return getStrongProxyForHandle(0);  
  6.   } else {  
  7.     return getContextObject(String16("default"), caller);  
  8.   }  
  9. }  
 

因为支持binder驱动(supportsProcesses()函数会判断binder驱动是否打开,以此来检验是否支持binder),所以会执行getStrongProxyForHandle(0)。(Handle 0就是service manager,之前已经提到过的BINDER_SERVICE_MANAGER,后面会进一步解释。)

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/ProcessState.cpp   
  2. sp ProcessState::getStrongProxyForHandle(int32_t handle)  
  3. {  
  4.   sp result;  
  5.   AutoMutex _l(mLock);  
  6.   handle_entry* e = lookupHandleLocked(handle);  
  7.   if (e != NULL) {  
  8.     // We need to create a new BpBinder if there isn't currently one, OR we   
  9.     // are unable to acquire a weak reference on this current one.  See comment   
  10.     // in getWeakProxyForHandle() for more info about this.   
  11.     IBinder* b = e->binder;  
  12.     if (b == NULL || !e->refs->attemptIncWeak(this)) {  
  13.       b = new BpBinder(handle);   
  14.       e->binder = b;  
  15.       if (b) e->refs = b->getWeakRefs();  
  16.       result = b;  
  17.     } else {  
  18.       // This little bit of nastyness is to allow us to add a primary   
  19.       // reference to the remote proxy when this team doesn't have one   
  20.       // but another team is sending the handle to us.   
  21.       result.force_set(b);  
  22.       e->refs->decWeak(this);  
  23.     }  
  24.   }  
  25.   return result;  
  26. }  
 

在第一次调用时,b为NULL,因此会先创建一个BpBinder实例。BpBinder is a base proxy class for remote binder object.

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/BpBinder.cpp   
  2. BpBinder::BpBinder(int32_t handle)  
  3.     : mHandle(handle)  
  4.     , mAlive(1)  
  5.     , mObitsSent(0)  
  6.     , mObituaries(NULL)  
  7. {  
  8.   LOGV("Creating BpBinder %p handle %d/n", this, mHandle);  
  9.   extendObjectLifetime(OBJECT_LIFETIME_WEAK);  
  10.   IPCThreadState::self()->incWeakHandle(handle);  
  11. }  
 

IPCThreadState::incWeakHandle将会在输出缓冲区(一个Parcel)中添加一个BC_INCREFS命令。

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/IPCThreadState.cpp   
  2. void IPCThreadState::incWeakHandle(int32_t handle)  
  3. {  
  4.   LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)/n", handle);  
  5.   mOut.writeInt32(BC_INCREFS);  
  6.   mOut.writeInt32(handle);  
  7. }  
 

现在getContextObject回返回一个BpBinder实例,改BpBinder实例会通过interface_cast转换为IserviceManager类型。interface_cast定义在IInterface.h头文件中。定义如下:

view plaincopy to clipboard?

  1. // frameworks/base/include/binder/IInterface.h   
  2. template  
  3. inline sp interface_cast(const sp& obj)  
  4. {  
  5.   return INTERFACE::asInterface(obj);  
  6. }  
 

现在让我们看一下IServiceManager的定义。

view plaincopy to clipboard?

  1. // frameworks/base/include/binder/IServiceManager.h   
  2. class IServiceManager : public Iinterface  
  3. {  
  4. public:  
  5.   DECLARE_META_INTERFACE(ServiceManager);  
  6.   /** 
  7.    * Retrieve an existing service, blocking for a few seconds 
  8.    * if it doesn't yet exist. 
  9.    */  
  10.   virtual sp         getService( const String16& name) const = 0;  
  11.   /** 
  12.    * Retrieve an existing service, non-blocking. 
  13.    */  
  14.   virtual sp         checkService( const String16& name) const = 0;  
  15.   /** 
  16.    * Register a service. 
  17.    */  
  18.   virtual status_t            addService( const String16& name,  
  19.                                     const sp& service) = 0;  
  20.   /** 
  21.    * Return list of all existing services. 
  22.    */  
  23.   virtual Vector    listServices() = 0;  
  24.   enum {  
  25.         GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,  
  26.         CHECK_SERVICE_TRANSACTION,  
  27.         ADD_SERVICE_TRANSACTION,  
  28.         LIST_SERVICES_TRANSACTION,  
  29.   };  
  30. };  
 

DECLARE_META_INTERFACE宏在IInterface.h头文件中定义如下:

view plaincopy to clipboard?

  1. // frameworks/base/include/binder/IInterface.h   
  2. #define DECLARE_META_INTERFACE(INTERFACE)              /   
  3.   static const String16 descriptor;                                  /  
  4.   static sp asInterface(const sp& obj);      /  
  5.   virtual const String16& getInterfaceDescriptor() const;               /  
  6.   I##INTERFACE();                                            /  
  7.   virtual ~I##INTERFACE();  
 

DECLARE_META_INTERFACE宏声明了两个函数,这两个函数通过在IServiceManager.cpp文件中调用IMPLEMENT_META_INTERFACE宏来实现。

view plaincopy to clipboard?

  1. // frameworks/base/libs/binder/IServiceManager.cpp   
  2. IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");  
 

IMPLEMENT_META_INTERFACE宏定义如下:

view plaincopy to clipboard?

  1. // frameworks/base/include/binder/IInterface.h   
  2. #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)           /   
  3.   const String16 I##INTERFACE::descriptor(NAME);                      /  
  4.   const String16& I##INTERFACE::getInterfaceDescriptor() const {           /  
  5.       return I##INTERFACE::descriptor;                                /  
  6.   }                                                                /  
  7.   sp I##INTERFACE::asInterface(const sp& obj)   /  
  8.   {                                                                /  
  9.     sp intr;                                          /  
  10.     if (obj != NULL) {                                                /  
  11.       intr = static_cast(                              /  
  12.            obj->queryLocalInterface(                                   /  
  13.                   I##INTERFACE::descriptor).get());                    /  
  14.       if (intr == NULL) {                                             /  
  15.         intr = new Bp##INTERFACE(obj);                              /  
  16.       }                                                            /  
  17.     }                                                              /  
  18.     return intr;                                                      /  
  19.   }                                                                /  
  20.   I##INTERFACE::I##INTERFACE() { }                                 /  
  21.   I##INTERFACE::~I##INTERFACE() { }                                /  
 

IServiceManager::asInterface()函数最终会创建一个BpServiceManager实例,并将它返回给用户。BpServiceManager是远程BnServiceManager的一个代理。任何针对IServiceManager的操作最终都会调用BpServiceManager中相应虚函数。

小结:

本节给出了如何获取一个远程对象的代理对象。

假设你要实现你自己的服务IfunnyTest,你需要做以下工作:

  • 将DECLARE_META_INTERFACE(FunnyTest)宏放进interface的头文件
  • 将IMPLEMENT_META_INTERFACE(Funnytest, “your unique name”)宏放入interface的源文件
  • 实现你自己的BpFunnyTest类