Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
在前面一篇文章浅谈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深入浅出之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 通信资料的整理,后续继续补充相关资料,谢谢大家对本站的支持!