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

相关文章

sqlserver、mysql、oracle、pgsql、sqlite五大关系数据库的对象名称和转义字符

《sqlserver、mysql、oracle、pgsql、sqlite五大关系数据库的对象名称和转义字符》:本文主要介绍sqlserver、mysql、oracle、pgsql、sqlite五大... 目录一、转义符1.1 oracle1.2 sqlserver1.3 PostgreSQL1.4 SQLi

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

k8s中实现mysql主备过程详解

《k8s中实现mysql主备过程详解》文章讲解了在K8s中使用StatefulSet部署MySQL主备架构,包含NFS安装、storageClass配置、MySQL部署及同步检查步骤,确保主备数据一致... 目录一、k8s中实现mysql主备1.1 环境信息1.2 部署nfs-provisioner1.2.

Java发送SNMP至交换机获取交换机状态实现方式

《Java发送SNMP至交换机获取交换机状态实现方式》文章介绍使用SNMP4J库(2.7.0)通过RCF1213-MIB协议获取交换机单/多路状态,需开启SNMP支持,重点对比SNMPv1、v2c、v... 目录交换机协议SNMP库获取交换机单路状态获取交换机多路状态总结交换机协议这里使用的交换机协议为常

使用MapStruct实现Java对象映射的示例代码

《使用MapStruct实现Java对象映射的示例代码》本文主要介绍了使用MapStruct实现Java对象映射的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、什么是 MapStruct?二、实战演练:三步集成 MapStruct第一步:添加 Mave