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

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6627260

在前面一篇文章浅谈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文件中:

[cpp] view plaincopy

  1. sp<IServiceManager> defaultServiceManager();

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

[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. }

gDefaultServiceManagerLock和gDefaultServiceManager是全局变量,定义在frameworks/base/libs/binder/Static.cpp文件中:

[cpp] view plaincopy

  1. Mutex gDefaultServiceManagerLock;
  2. 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文件中:

[cpp] view plaincopy

  1. template<typename INTERFACE>
  2. class BpInterface : public INTERFACE, public BpRefBase
  3. {
  4. public:
  5. BpInterface(const sp<IBinder>& remote);
  6. protected:
  7. virtual IBinder* onAsBinder();
  8. };

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远程接口主要是下面语句:

[cpp] view plaincopy

  1. gDefaultServiceManager = interface_cast<IServiceManager>(
  2. 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远程接口的语句可以简化为:

[cpp] view plaincopy

  1. gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));

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

[cpp] view plaincopy

  1. template<typename INTERFACE>
  2. inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
  3. {
  4. return INTERFACE::asInterface(obj);
  5. }

这里的INTERFACE是IServiceManager,于是调用了IServiceManager::asInterface函数。IServiceManager::asInterface是通过DECLARE_META_INTERFACE(ServiceManager)宏在IServiceManager类中声明的,它位于framework/base/include/binder/IServiceManager.h文件中:

[cpp] view plaincopy

  1. DECLARE_META_INTERFACE(ServiceManager);

展开即为:

[cpp] view plaincopy

  1. #define DECLARE_META_INTERFACE(ServiceManager)                              \
  2. static const android::String16 descriptor;                          \
  3. static android::sp<IServiceManager> asInterface(                    \
  4. const android::sp<android::IBinder>& obj);                          \
  5. virtual const android::String16& getInterfaceDescriptor() const;    \
  6. IServiceManager();                                                  \
  7. virtual ~IServiceManager();

IServiceManager::asInterface的实现是通过IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")宏定义的,它位于framework/base/libs/binder/IServiceManager.cpp文件中:

[cpp] view plaincopy

  1. IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

展开即为:

[cpp] view plaincopy

  1. #define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")                 \
  2. const android::String16 IServiceManager::descriptor("android.os.IServiceManager");     \
  3. const android::String16&                                   \
  4. IServiceManager::getInterfaceDescriptor() const {                                      \
  5. return IServiceManager::descriptor;                                                    \
  6. }                                                                                      \
  7. android::sp<IServiceManager> IServiceManager::asInterface(                             \
  8. const android::sp<android::IBinder>& obj)                                              \
  9. {                                                                                      \
  10. android::sp<IServiceManager> intr;                                                     \
  11. if (obj != NULL) {                                                                     \
  12. intr = static_cast<IServiceManager*>(                                                  \
  13. obj->queryLocalInterface(                                                              \
  14. IServiceManager::descriptor).get());                                                   \
  15. if (intr == NULL) {                                                                    \
  16. intr = new BpServiceManager(obj);                                                      \
  17. }                                                                                      \
  18. }                                                                                      \
  19. return intr;                                                                           \
  20. }                                                                                      \
  21. IServiceManager::IServiceManager() { }                                                 \
  22. IServiceManager::~IServiceManager() { }

估计写这段代码的员工是从Microsoft跳槽到Google的。这里我们关注IServiceManager::asInterface的实现:

[cpp] view plaincopy

  1. android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)
  2. {
  3. android::sp<IServiceManager> intr;
  4. if (obj != NULL) {
  5. intr = static_cast<IServiceManager*>(
  6. obj->queryLocalInterface(IServiceManager::descriptor).get());
  7. if (intr == NULL) {
  8. intr = new BpServiceManager(obj);
  9. }
  10. return intr;
  11. }

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

[cpp] view plaincopy

  1. sp<IInterface>  IBinder::queryLocalInterface(const String16& descriptor)
  2. {
  3. return NULL;
  4. }

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

[cpp] view plaincopy

  1. intr = new BpServiceManager(obj);

即为:

[cpp] view plaincopy

  1. intr = new BpServiceManager(new BpBinder(0));

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

[cpp] view plaincopy

  1. 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进程间通信机制,敬请关注。

老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

时间: 2024-10-11 23:22:51

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

Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6629298 在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路中, 介绍了在Android系统中Binder进程间通信机制中的Server角色是如何获得Service Manager远程接口的,即defaultServiceManager函数的实现.S

浅谈Android系统开发中LOG的使用

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6581828 在程序开发过程中,LOG是广泛使用的用来记录程序执行过程的机制,它既可以用于程序调试,也可以用于产品运营中的事件记录.在Android系统中,提供了简单.便利的LOG机制,开发人员可以方便地使用.在这一篇文章中,我们简单介绍在Android内核空间和用户空间中LOG的使用和查看方法. 一. 内核开发时LOG的使用.Android内核

浅谈Android系统的图标设计规范

http://homepage.yesky.com/89/11620089.shtml 目前移动平台的竞争日益激烈,友好的用户界面可以帮助提高用户体验满意度,图标Icon是用户界面中一个重要的组成部分,今天我们来研究和学习一下Android系统的图标设计规范.在探讨Android的icon设计之前,我们有必要先了解Android的界面是如何适配多样化屏幕的. 适配性 由于同一个UI元素(如100 x100像素的图片)在高精度的屏幕上要比低精度的屏幕上看起来要小,为了让这两个屏幕上的图片看起来效果

Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6633311 在上一篇文章中,我 们分析了Android系统进程间通信机制Binder中的Server在启动过程使用Service Manager的addService接口把自己添加到Service Manager守护过程中接受管理.在这一篇文章中,我们将深入到Binder驱动程序源代码去分析Client是如何通过Service Manager的

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机

浅谈Android五大布局

Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Android的五大布局分别是LinearLayout(线性布局).FrameLayout(单帧布局).RelativeLayout(相对布局).AbsoluteLayout(绝对布局)和TableLayout(表格布局). LinearLayout: LinearLayout按照垂直或者水平的顺序依次排列子元素,每一个子元素都位于前一个元素之后

浅谈Android五大布局(二)——RelativeLayout和TableLayout

在浅谈Android五大布局(一)中已经描述了LinearLayout(线性布局).FrameLayout(单帧布局)和AbsoulteLayout(绝对布局)三种布局结构,剩下的两种布局RelativeLayout(相对布局)和TableLayout(表格布局)相对之前布局结构稍显复杂一点,所以这里另起篇幅进行介绍. RelativeLayout: RelativeLayout按照各子元素之间的位置关系完成布局.在此布局中的子元素里与位置相关的属性将生效.例如android:layout_be

浅谈Android五大布局(二)——RelativeLayout和TableLayout【转】

http://www.cnblogs.com/wisekingokok/archive/2011/08/24/2152004.html 在浅谈Android五大布局(一)中已经描述了LinearLayout(线性布局).FrameLayout(单帧布局)和AbsoulteLayout(绝对布局)三种布局结构,剩下的两种布局RelativeLayout(相对布局)和TableLayout(表格布局)相对之前布局结构稍显复杂一点,所以这里另起篇幅进行介绍. RelativeLayout: Relat

浅谈Android 事件分发机制(一)

在上一篇文章中,浅谈Android 事件分发机制(一),简要分析了一下事件分发机制的原理,总结一下就是事件层层传递,直到被消费,原理看似简单,但是在实际使用过程中,场景各不相同,复杂程度也就因产品而异,这篇文章就通过给view加移动来模拟事件分发. 触摸事件 这里涉及到几个与手指触摸相关的常见事件: 坐标系对于单指触控移动来说,一次简单的交互流程是这样的:手指落下(ACTION_DOWN) -> 移动(ACTION_MOVE) -> 离开(ACTION_UP) 坐标系 Android坐标系以手