浅谈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文件中:

 


  
  
  1. sp<IServiceManager> defaultServiceManager(); 

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

 


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

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


  
  
  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文件中:
 


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

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


  
  
  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远程接口的语句可以简化为:

 


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

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

 


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

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

 


  
  
  1. DECLARE_META_INTERFACE(ServiceManager); 

    展开即为:

 


  
  
  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文件中:

 


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

      展开即为:

 


  
  
  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的实现:

 


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

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

 


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

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

 


  
  
  1. intr = new BpServiceManager(obj);  

    即为:


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

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

 


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





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/964530,如需转载请自行联系原作者

目录
相关文章
|
4月前
|
存储 Linux Android开发
Android底层:通熟易懂分析binder:1.binder准备工作
本文详细介绍了Android Binder机制的准备工作,包括打开Binder驱动、内存映射(mmap)、启动Binder主线程等内容。通过分析系统调用和进程与驱动层的通信,解释了Binder如何实现进程间通信。文章还探讨了Binder主线程的启动流程及其在进程通信中的作用,最后总结了Binder准备工作的调用时机和重要性。
Android底层:通熟易懂分析binder:1.binder准备工作
|
6月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
7月前
|
缓存 安全 Java
Android深入Binder拦截问题分析
【7月更文挑战第1天】Android Binder 拦截可实现虚拟化、测试、SDK检测、逆向分析及ROM扩展。通过Java层aidl代理,利用IBinder接口规范来拦截通信。拦截步骤包括:替换Binder服务缓存对象,如ActivityManagerService;代理ServiceManager以控制服务获取。此操作需系统权限,可能涉及安全风险和版本差异,非必要时应谨慎。
|
8月前
|
调度 Android开发
43. 【Android教程】服务:Service
43. 【Android教程】服务:Service
72 2
|
9月前
|
数据采集 Python SQL
2024年校花转学到我们班,于是我用Python把她空间给爬了个遍!(1),binder机制面试题
2024年校花转学到我们班,于是我用Python把她空间给爬了个遍!(1),binder机制面试题
2024年校花转学到我们班,于是我用Python把她空间给爬了个遍!(1),binder机制面试题
|
9月前
|
Android开发 移动开发 小程序
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
|
9月前
|
存储 监控 Java
Android Service之设备存储空间监控 DeviceStorageMonitorService
Android Service之设备存储空间监控 DeviceStorageMonitorService
170 2
|
9月前
|
Android开发 数据库管理
Android如何在Activity和Service之间传递数据
Android如何在Activity和Service之间传递数据
343 3
|
9月前
|
Android开发
Android Service的两种使用方法
Android Service的两种使用方法
61 2
|
6月前
|
算法 Linux 调度
探索进程调度:Linux内核中的完全公平调度器
【8月更文挑战第2天】在操作系统的心脏——内核中,进程调度算法扮演着至关重要的角色。本文将深入探讨Linux内核中的完全公平调度器(Completely Fair Scheduler, CFS),一个旨在提供公平时间分配给所有进程的调度器。我们将通过代码示例,理解CFS如何管理运行队列、选择下一个运行进程以及如何对实时负载进行响应。文章将揭示CFS的设计哲学,并展示其如何在现代多任务计算环境中实现高效的资源分配。

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    Android历史版本与APK文件结构
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 8
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 9
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 相关实验场景

    更多