Android Binder进程间通信-ServiceManager代理对象的获取过程

本文主要是介绍Android Binder进程间通信-ServiceManager代理对象的获取过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章来源:http://www.itnose.net/detail/6043249.html
更多文章:http://www.itnose.net/type/85.html

一、测试代码:

       ~/Android/external/binder/server

        ----FregServer.cpp

        ~/Android/external/binder/common

        ----IFregService.cpp

        ----IFregService.h

       ~/Android/external/binder/client

       ----FregClient.cpp

 

       Binder库(libbinder)代码:

       ~/Android/frameworks/base/libs/binder

       ----BpBinder.cpp

       ----Parcel.cpp

       ----ProcessState.cpp

       ----Binder.cpp

       ----IInterface.cpp

       ----IPCThreadState.cpp

       ----IServiceManager.cpp

       ----Static.cpp

       ~/Android/frameworks/base/include/binder

       ----Binder.h

       ----BpBinder.h

       ----IInterface.h

       ----IPCThreadState.h

       ----IServiceManager.h

       ----IBinder.h

       ----Parcel.h

       ----ProcessState.h

 

        驱动层代码:

       ~/Android//kernel/goldfish/drivers/staging/android

       ----binder.c

       ----binder.h

 

二、源码分析

      1、程序首先开始从Service进程FregServer.cpp的main函数开始执行

     ~/Android/external/binder/server

     ----FregServer.cpp

 

class FregService : public BnFregService
{...........
public:static void instantiate(){defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());}...........
};int main(int argc, char** argv)
{FregService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();return 0;
}
      main函数首先调用静态方法instantiate,在instantiate中调用了defaultServiceManager(), defaultServiceManager()函数实现如下:

 

     

      ~/Android/frameworks/base/libs/binder

      ----IServiceManager.cpp

 

sp<IServiceManager> defaultServiceManager()
{if (gDefaultServiceManager != NULL) return gDefaultServiceManager;//如果已经创建了代理对象,那么就直接返回{AutoMutex _l(gDefaultServiceManagerLock);//使用锁,来实现单例模式if (gDefaultServiceManager == NULL) {gDefaultServiceManager = interface_cast<IServiceManager>(//分三步获取Service Manager代理对象ProcessState::self()->getContextObject(NULL));}}return gDefaultServiceManager;
}
      其中gDefaultServiceManagerLock,gDefaultServiceManager都定义在Static.cpp中。

 

       ~/Android/frameworks/base/libs/binder

       ----Static.cpp

 

Mutex gDefaultServiceManagerLock;   //锁
sp<IServiceManager> gDefaultServiceManager; //IServiceManager的强指针
       全局变量 gDefaultServiceManager是一个类型为IServiceManager的强指针,它指向进程内的一个BpServiceManager对象,即Service Manager代理对象;而全局变量gDefaultServiceManagerLock是用来保证一个进程至多只有一个Service Manager代理对象。结合锁机制来保证对象在进程中的唯一性,这是单例设计模式的经典实现。

 

       如果已经创建了代理对象,那么就直接返回。如果没有创建,那么分三步创建:

       (1)、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象。

       (2)、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象

       (3)、调用模板函数interface_cast<IServiceManager>将前面获得的Binder代理对象封装成一个Service Manager代理对象。

 

        2、调用ProcessState类的静态成员函数self获取进程内的一个ProcessState对象

       ~/Android/frameworks/base/libs/binder

       ----ProcessState.cpp

 

sp<ProcessState> ProcessState::self()
{if (gProcess != NULL) return gProcess;//如果已经创建了,就直接返回AutoMutex _l(gProcessMutex);if (gProcess == NULL) gProcess = new ProcessState;//创建ProcessState对象return gProcess;
}
      其中gProcess,gProcessMutex都位于Static.cpp中

 

 

Mutex gProcessMutex;
sp<ProcessState> gProcess;
      全局变量gProcess是一个类型为ProcessState的强指针,它指向进程内的一个ProcessState对象;而全局变量gProcessMutex是一个互斥锁,是用来保证一个进程至多只有一个ProcessState对象的,同样是一个单例模式。

 

 

      首次进入,故创建ProcessState对象。

 

      ~/Android/frameworks/base/libs/binder

      ----ProcessState.cpp

 

ProcessState::ProcessState(): mDriverFD(open_driver()), mVMStart(MAP_FAILED).....
{if (mDriverFD >= 0) {...........// mmap the binder, providing a chunk of virtual address space to receive transactions.mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);...........
}
     在初始化构造函数中调用了open_driver方法。

 

      ~/Android/frameworks/base/libs/binder

      ----ProcessState.cpp

 

static int open_driver()
{if (gSingleProcess) {return -1;}int fd = open("/dev/binder", O_RDWR);//又一个进程打开了设备文件,binder_procs又多了一个进程的结构体if (fd >= 0) {fcntl(fd, F_SETFD, FD_CLOEXEC);int vers;
#if defined(HAVE_ANDROID_OS)status_t result = ioctl(fd, BINDER_VERSION, &vers);
#elsestatus_t result = -1;errno = EPERM;
#endifif (result == -1) {LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));close(fd);fd = -1;}if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {LOGE("Binder driver protocol does not match user space protocol!");close(fd);fd = -1;}
#if defined(HAVE_ANDROID_OS)size_t maxThreads = 15;result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);if (result == -1) {LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));}
#endif} else {LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));}return fd;
}
      open_driver首先调用了open打开设备文件,在http://blog.csdn.net/jltxgcy/article/details/25797011这盘文章中已经讲解了驱动层的binder_open所做的事。然后的调用ioctl传入BINDER_VERSION参数来获取vers。最后调用ioctl传入BINDER_SET_MAX_THREADS参数来设备该进程所支持的最大线程数。

 

     

      在初始化列表中调用mmap把设备文件/dev/binder映射到进程的地址空间,其实将/dev/binder映射到进程的地址空间实际上是请求Binder驱动程序为进程分配内核缓冲区。


      3、调用前面获得的ProcessState对象的成员函数getContextObject创建一个Binder代理对象

      ~/Android/frameworks/base/libs/binder

      ----ProcessState.cpp

 

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{if (supportsProcesses()) {return getStrongProxyForHandle(0);} else {return getContextObject(String16("default"), caller);}
}

 

这篇关于Android Binder进程间通信-ServiceManager代理对象的获取过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944797

相关文章

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os