欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

程序员文章站 2024-03-06 20:12:38
        在前面一篇文章浅谈service manager成为android进程间通信(ipc)...

        在前面一篇文章浅谈service manager成为android进程间通信(ipc)机制binder守护进程之路中,介绍了service manager是如何成为binder机制的守护进程的。既然作为守护进程,service manager的职责当然就是为server和client服务了。那么,server和client如何获得service manager接口,进而享受它提供的服务呢?本文将简要分析server和client获得service manager的过程。

        在阅读本文之前,希望读者先阅读android进程间通信(ipc)机制binder简要介绍和学习计划一文提到的参考资料android深入浅出之binder机制,这样可以加深对本文的理解。

        我们知道,service manager在binder机制中既充当守护进程的角色,同时它也充当着server角色,然而它又与一般的server不一样。对于普通的server来说,client如果想要获得server的远程接口,那么必须通过service manager远程接口提供的getservice接口来获得,这本身就是一个使用binder机制来进行进程间通信的过程。而对于service manager这个server来说,client如果想要获得service manager远程接口,却不必通过进程间通信机制来获得,因为service manager远程接口是一个特殊的binder引用,它的引用句柄一定是0。

        获取service manager远程接口的函数是defaultservicemanager,这个函数声明在frameworks/base/include/binder/iservicemanager.h文件中:

          sp<iservicemanager> defaultservicemanager();  

      实现在frameworks/base/libs/binder/iservicemanager.cpp文件中:

sp<iservicemanager> defaultservicemanager() 
{ 
 
 if (gdefaultservicemanager != null) return gdefaultservicemanager; 
 
 { 
  automutex _l(gdefaultservicemanagerlock); 
  if (gdefaultservicemanager == null) { 
   gdefaultservicemanager = interface_cast<iservicemanager>( 
    processstate::self()->getcontextobject(null)); 
  } 
 } 
 
 return gdefaultservicemanager; 
} 

        gdefaultservicemanagerlock和gdefaultservicemanager是全局变量,定义在frameworks/base/libs/binder/static.cpp文件中:

mutex gdefaultservicemanagerlock; 
sp<iservicemanager> gdefaultservicemanager; 

        从这个函数可以看出,gdefaultservicemanager是单例模式,调用defaultservicemanager函数时,如果gdefaultservicemanager已经创建,则直接返回,否则通过interface_cast<iservicemanager>(processstate::self()->getcontextobject(null))来创建一个,并保存在gdefaultservicemanager全局变量中。

       在继续介绍interface_cast<iservicemanager>(processstate::self()->getcontextobject(null))的实现之前,先来看一个类图,这能够帮助我们了解service manager远程接口的创建过程。

Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路

        参考资料android深入浅出之binder机制一文的读者,应该会比较容易理解这个图。这个图表明了,bpservicemanager类继承了bpinterface<iservicemanager>类,bpinterface是一个模板类,它定义在frameworks/base/include/binder/iinterface.h文件中:

template<typename interface> 
class bpinterface : public interface, public bprefbase 
{ 
public: 
 bpinterface(const sp<ibinder>& remote); 
 
protected: 
 virtual ibinder* onasbinder(); 
}; 

        iservicemanager类继承了iinterface类,而iinterface类和bprefbase类又分别继承了refbase类。在bprefbase类中,有一个成员变量mremote,它的类型是ibinder*,实现类为bpbinder,它表示一个binder引用,引用句柄值保存在bpbinder类的mhandle成员变量中。bpbinder类通过ipcthreadstate类来和binder驱动程序并互,而ipcthreadstate又通过它的成员变量mprocess来打开/dev/binder设备文件,mprocess成员变量的类型为processstate。processstate类打开设备/dev/binder之后,将打开文件描述符保存在mdriverfd成员变量中,以供后续使用。

        理解了这些概念之后,就可以继续分析创建service manager远程接口的过程了,最终目的是要创建一个bpservicemanager实例,并且返回它的iservicemanager接口。创建service manager远程接口主要是下面语句:

gdefaultservicemanager = interface_cast<iservicemanager>( 
    processstate::self()->getcontextobject(null));  

        看起来简短,却暗藏玄机,具体可阅读android深入浅出之binder机制这篇参考资料,这里作简要描述。

        首先是调用processstate::self函数,self函数是processstate的静态成员函数,它的作用是返回一个全局唯一的processstate实例变量,就是单例模式了,这个变量名为gprocess。如果gprocess尚未创建,就会执行创建操作,在processstate的构造函数中,会通过open文件操作函数打开设备文件/dev/binder,并且返回来的设备文件描述符保存在成员变量mdriverfd中。

        接着调用gprocess->getcontextobject函数来获得一个句柄值为0的binder引用,即bpbinder了,于是创建service manager远程接口的语句可以简化为:

gdefaultservicemanager = interface_cast<iservicemanager>(new bpbinder(0));  

        再来看函数interface_cast<iservicemanager>的实现,它是一个模板函数,定义在framework/base/include/binder/iinterface.h文件中:

template<typename interface> 
inline sp<interface> interface_cast(const sp<ibinder>& obj) 
{ 
 return interface::asinterface(obj); 
} 

    这里的interface是iservicemanager,于是调用了iservicemanager::asinterface函数。iservicemanager::asinterface是通过declare_meta_interface(servicemanager)宏在iservicemanager类中声明的,它位于framework/base/include/binder/iservicemanager.h文件中:

declare_meta_interface(servicemanager);  

        展开即为:

#define declare_meta_interface(servicemanager)        \ 
 static const android::string16 descriptor;       \ 
 static android::sp<iservicemanager> asinterface(     \ 
 const android::sp<android::ibinder>& obj);       \ 
 virtual const android::string16& getinterfacedescriptor() const; \ 
 iservicemanager();             \ 
 virtual ~iservicemanager();           
  

  iservicemanager::asinterface的实现是通过implement_meta_interface(servicemanager, "android.os.iservicemanager")宏定义的,它位于framework/base/libs/binder/iservicemanager.cpp文件中:

implement_meta_interface(servicemanager, "android.os.iservicemanager");  

       展开即为:

#define implement_meta_interface(servicemanager, "android.os.iservicemanager")     \ 
 const android::string16 iservicemanager::descriptor("android.os.iservicemanager");  \ 
 const android::string16&         \ 
 iservicemanager::getinterfacedescriptor() const {          \ 
 return iservicemanager::descriptor;             \ 
 }                      \ 
 android::sp<iservicemanager> iservicemanager::asinterface(        \ 
 const android::sp<android::ibinder>& obj)            \ 
 {                      \ 
 android::sp<iservicemanager> intr;              \ 
 if (obj != null) {                  \ 
 intr = static_cast<iservicemanager*>(             \ 
 obj->querylocalinterface(                \ 
 iservicemanager::descriptor).get());             \ 
 if (intr == null) {                 \ 
 intr = new bpservicemanager(obj);              \ 
 }                      \ 
 }                      \ 
 return intr;                   \ 
 }                      \ 
 iservicemanager::iservicemanager() { }             \ 
 iservicemanager::~iservicemanager() { }  

         估计写这段代码的员工是从microsoft跳槽到google的。这里我们关注iservicemanager::asinterface的实现:

android::sp<iservicemanager> iservicemanager::asinterface(const android::sp<android::ibinder>& obj)            
{                      
 android::sp<iservicemanager> intr;              
  
 if (obj != null) {                  
  intr = static_cast<iservicemanager*>(             
     obj->querylocalinterface(iservicemanager::descriptor).get()); 
   
  if (intr == null) {     
   intr = new bpservicemanager(obj);           
  }           
 } 
 return intr;         
}  

         这里传进来的参数obj就则刚才创建的new bpbinder(0)了,bpbinder类中的成员函数querylocalinterface继承自基类ibinder,ibinder::querylocalinterface函数位于framework/base/libs/binder/binder.cpp文件中:

sp<iinterface> ibinder::querylocalinterface(const string16& descriptor) 
{ 
 return null; 
} 

         由此可见,在iservicemanager::asinterface函数中,最终会调用下面语句:

                    intr = new bpservicemanager(obj);   

         即为:

                    intr = new bpservicemanager(new bpbinder(0));   

        回到defaultservicemanager函数中,最终结果为:

           gdefaultservicemanager = new bpservicemanager(new bpbinder(0));  

       这样,service manager远程接口就创建完成了,它本质上是一个bpservicemanager,包含了一个句柄值为0的binder引用。

        在android系统的binder机制中,server和client拿到这个service manager远程接口之后怎么用呢?

        对server来说,就是调用iservicemanager::addservice这个接口来和binder驱动程序交互了,即调用bpservicemanager::addservice 。而bpservicemanager::addservice又会调用通过其基类bprefbase的成员函数remote获得原先创建的bpbinder实例,接着调用bpbinder::transact成员函数。在bpbinder::transact函数中,又会调用ipcthreadstate::transact成员函数,这里就是最终与binder驱动程序交互的地方了。回忆一下前面的类图,ipcthreadstate有一个porcessstate类型的成中变量mprocess,而mprocess有一个成员变量mdriverfd,它是设备文件/dev/binder的打开文件描述符,因此,ipcthreadstate就相当于间接在拥有了设备文件/dev/binder的打开文件描述符,于是,便可以与binder驱动程序交互了。

       对client来说,就是调用iservicemanager::getservice这个接口来和binder驱动程序交互了。具体过程上述server使用service manager的方法是一样的,这里就不再累述了。

      iservicemanager::addservice和iservicemanager::getservice这两个函数的具体实现,在下面两篇文章中,会深入到binder驱动程序这一层,进行详细的源代码分析,以便更好地理解binder进程间通信机制,敬请关注。

        以上就是对android binder 通信资料的整理,后续继续补充相关资料,谢谢大家对本站的支持!