9.8 Binder系统_c++实现_内部机制1
1. 内部机制_回顾binder框架关键点
binder进程通讯过程情景举例:
test_server通过addservice向service_manager注册服务
test_client通过getservice向service_manager获取服务
然后test_client使用服务和test_server通讯
在上述通讯过程中涉及的对驱动访问:
(1)注册服务过程add_service
a、test_server为每个服务构造一个flat_binder_object结构体,不同服务结构体的binder和cookie不同
b、调用ioctl发送数据(数据包括:flat_binder_object、服务名称、目的发给谁(handle = 0,表示发给service_manager))
c、驱动程序对每一个flat_binder_object为test_server进程新建binder_node节点,节点的ptr和cookie参数值来之flat_binder_object结构体的binder和cookie
d、驱动程序根据handle=0,找到service_manager,把数据发送给它,且为service_manager进程创建binder_ref结构体,并根据binder_ref创建的顺序设置其desc参数和node指向对应的binder_node
e、service_manager里,记录服务的名称和的desc值,在service_manager应用程序中有svclist链表,链表的每个节点保存有服务的名称和的handle值(其值等于desc)
(2)获取服务过程get_service
a、test_client构造数据(数据:服务的名称、目的(handle = 0))
b、调用ioctl发送数据
c、驱动程序根据handle=0,找到service_manager,把数据发送给它
d、service_manager从svclist根据服务的名字找到对应的项,取出对应节点的handle
e、service_manager通过ioctl返回数据(数据的格式:flat_binder_object(type是引用、handle、cookie))
f、驱动程序发现数据中含有flat_binder_object结构体,且type表示引用,从service_manager进程的binder_ref中找到desc等于handle的一项,找根据binder_node找到对应的服务,最后为test_client进程建立binder_ref,根据test_client获取服务的顺序设置test_client进程你binder_ref的desc值,并设置其node执行对应的服务binder_node
(3)test_client怎么使用helloservice
a、构造数据(数据包含:code(和服务端约定的代表函数的值)、参数、目的(根据服务确定handle值))
b、使用ioctl发数据
c、驱动程序从数据中取出handle,根据handle找到test_client进程里的binder_ref,根据其找到binder_node,在根据binder_node里面的proc找到服务进程,把数据给test_server,并且在数据中设置ptr和cookie,这两个变量等于binder_node的ptr和cookie
d、test_server根据ptr和cookie知道你想调用哪个服务,在根据数据里的code来调用哪个函数
server注册服务时, 对每个服务都提供不同的ptr/cookie,
在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie
client使用服务前要先getService:会在驱动程序里对该服务构造一个binder_ref,
binder_ref含有desc, node成员, desc是整数, node指向对应服务的binder_node
使用服务时, client构造数据,调用ioctl:数据里含有handle
驱动程序根据handle找到binder_ref(desc==handle), 找到binder_node, 再找到server,
从binder_node取出ptr/cookie连同那些数据发给server
server根据ptr/cookie知道要调用哪一个服务,....
最核心函数: ioctl
client的最核心数据是:handle
server的最核心数据是:ptr/cookie
4. 内部机制_代理类分析: BpServiceManager和BpHelloService
test_client与test_server之间通信在C++中是通过代理类BpHelloService来实现(这个时候test_client是client,test_server是server)
test_server向service_manager添加服务的过程是通过代理类BpServiceManager来实现的(这个时候test_server是client,service_manager是server)
test_client向service_manager获得服务的过程是通过代理类BpServiceManager来实现的(这个时候test_client是client,service_manager是server)
根据上面那节内容:client的最核心数据是:handle
那么对于类BpServiceManager:传给它的handle = 0;
那么对于类BpHelloService:传给它的handle = BpServiceManager->getservice("hello")返回的handle值
4.1 获得BpServiceManager对象的过程:
defaultServiceManager构造了一个BpServiceManager对象,
其中它的mRemote = new BpBinder(0); // mRemote->mHandle=0
defaultServiceManager(单例模式,一个进程中只有一个) // IServiceManager.cpp
// 把BpBinder(mHandle=0)对象转换为IServiceManager接口(BpServiceManager)
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));
分析:
ProcessState::self()->getContextObject(NULL)
getStrongProxyForHandle(0);
b = new BpBinder(handle); // mHandle=handle=0
interface_cast<IServiceManager>(new BpBinder(0)) // IInterface.h
IServiceManager::asInterface(obj);
return new BpServiceManager(obj); // mRemote=obj=new BpBinder(0);
4.2 获得BpHelloService对象的过程:
调用BpServiceManager的getService函数获得一个flat_binder_object,
从中取出handle, 创建一个BpBinder(handle),
然后使用interface_cast使用这个BpBinder创建一个BpHelloService对象
// binder是BpBinder对象, 里面含有HelloService的handle
sp<IBinder> binder = sm->getService(String16("hello")); // IServiceManager.cpp
// 构造数据: 数据中肯定含有"hello"
// 发送数据: 给handle 0, 即 service_manager进程
// 从收到的回复中取出HelloService的handle
return reply.readStrongBinder();
unflatten_binder(ProcessState::self(), *this, &val);
*out = proc->getStrongProxyForHandle(flat->handle);
new BpBinder(handle);
// 把binder转换为IHelloService接口(BpHelloService对象)
// binder是BpBinder对象, 里面含有HelloService的handle
sp<IHelloService> service = interface_cast<IHelloService>(binder);
4.3 代理类如何发送数据: ioctl, 数据里含有handle, 含有其他构造的参数
构造好数据之后,调用:
remote()->transact(...)
IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
5. 内部机制_数据传输: ProcessState和IPCThreadState
test_server主进程open、mmap的操作通过sp<ProcessState> proc(ProcessState::self())来实现
类对象是ProcessState,其是单例模式,每个进程只有一个ProcessState,通过ProcessState::self来得到对象gProcess
test_server会根据情况创建多个线程,每个线程有一个IPCThreadState,其也是单例模式,通过IPCThreadState::self来得到对象
ProcessState:
gProcess = new ProcessState时open和mmap,fd存在mDriverFD里
每个线程都有自己的IPCThreadState对象,该对象是线程特有的,各自不同,它应该存在线程的局部空间里,在进程中通过pthread_key_create()创建一个key,有key就有value,键值对。同一个key对于线程其可以设置不同的value
在线程1中通过pthread_setspecific(k,v1)设置,通过pthread_getspecific(k)获得进程v1
在线程1中通过pthread_setspecific(k,v2)设置,通过pthread_getspecific(k)获得进程v2
即线程共用同一个键,对于不同的值
IPCThreadState
ProcessState::self()->startThreadPool();//创建子线程,其就是在子线程中执行IPCThreadState::self()->joinThreadPool()来创建线程
IPCThreadState::self()->joinThreadPool();//主线程
IPCThreadState::self()这个函数第一次调用的时候会通过pthread_getspecific(k)来获取Value,这个Value就是IPCThreadState对象,第一次获取肯定为空,这个时候创建IPCThreadState对象,并且通过pthread_setspecific设置自身为Value,以后在调用IPCThreadState::self()的时候直接获得第一次创建的IPCThreadState,这样就能保证每一个线程只有一个IPCThreadState
5.1 addService
对于不同服务,构造flat_binder_object结构体,里面的.binder/.cookie对于不同的服务它的值不一样
sm->addService(String16("hello"), new BnHelloService());
data.writeStrongBinder(service); // service = new BnHelloService();
flatten_binder(ProcessState::self(), val, this); // val = service = new BnHelloService();
flat_binder_object obj; // 参数 binder = val = service = new BnHelloService();
IBinder *local = binder->localBinder(); // local =this = new BnHelloService();
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local); // new BnHelloService();
5.2 server如何分辨client想使用哪一个服务
server收到数据里含有flat_binder_object结构体,
它可以根据.binder/.cookie分析client想使用哪一个服务
把.cookie转换为BnXXXX对象,然后调用它的函数:
// 根据cookie构造了一个BBinder指针, 实际上是指向某个BnXXX对象(BBinder是其父类)
sp<BBinder> b((BBinder*)tr.cookie);
// 然后调用它的transact函数
error = b->transact(tr.code, buffer, &reply, tr.flags);
err = onTransact(code, data, reply, flags); // 就会调用到BnXXX里实现的onTransact
// 它就会根据code值来调用不同的函数
5.3 怎么调用到HelloService所提供的函数
9.8 Binder系统_c++实现_内部机制1的更多相关文章
- 9.13 Binder系统_Java实现_内部机制_Server端
logcat TestServer:* TestClient:* HelloService:* *:S &CLASSPATH=/mnt/android_fs/TestServer.jar ap ...
- 9.12 Binder系统_Java实现_内部机制_Client端
Java实现中client端的RPC层(java实现)如何通过JNI来调用IPC层(C++实现)发送数据 TestServer通过addService向Service_manager注册的时候Test ...
- 9.7 Binder系统_c++实现_编写程序
参考文件:frameworks\av\include\media\IMediaPlayerService.h (IMediaPlayerService,BnMediaPlayerService)fra ...
- 9.1 Binder系统_C程序示例_框架分析和编写程序
IPC : Inter-Process Communication, 进程间通信 A进程把数据原原本本的发给B,这就是IPC RPC : Remote Procedure Call, 远程过程调用 A ...
- 9.2 Binder系统_驱动情景分析_服务注册过程
1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...
- Android驱动学习-内部机制_回顾binder框架关键点
内部机制_回顾binder框架关键点server注册服务时, 对每个服务都提供不同的ptr/cookie,在驱动程序里对每个服务都构造一个binder_node, 它也含有ptr/cookie cli ...
- 9.11 Binder系统_分层
1.Binder系统过程分析,情景分析 server提供服务 (1)addService(服务名称,xxx)执行后会导致binder驱动在server的内核空间为服务创建一个binder_node结构 ...
- Android系统--Binder系统具体框架分析(一)
Binder系统具体框架分析(一) 一.Binder系统核心框架 1. IPC:Inter-Process Communication, 进程间通信 A进程将数据原原本本发送B进程,主要负责进程间数据 ...
- 012_STM32程序移植之_内部flash开机次数管理lib库建立
012_STM32程序移植之_内部flash开机次数管理lib库建立 1. 测试环境:STM32C8T6 2. 测试接口: 3. 串口使用串口一,波特率9600 单片机引脚------------CH ...
随机推荐
- js---16继承
123 instanceof Number;//false,要左边是对象右边是函数 typeof 123 ; //number new Number(123) instanceof Number; / ...
- 关于node的fs路径问题
我在写一个静态网页的服务器中遇到的一个问题,当时没理解就去查了 因为要访问最外部的json文件,就定义了一个模块读取文件,然后在外边的server.js中调用 但是一直路径错误. 我相信很多人和我一样 ...
- jsp&servlet报红线javax.servlet.jsp.XXXX cannot be resolved to a type类似错误解决办法
javax.servlet.jsp.JspException cannot be resolved to a type javax.servlet.jsp.PageContext cannot be ...
- mybatis的XML返回值类型报错
昨天项目里一直报错说是一个文件里的返回值java.util.hashmap不对,然后去定位这个文件发现并没有问题,后来在全局搜索的帮助下查找了返回值类型为resultMap的文件里看到写的代码里有: ...
- kali之Nmap (Network Mapper(网络映射器)
Nmap是主机扫描工具,他的图形化界面是Zenmap,分布式框架为Dnamp. Nmap可以完成以下任务: 主机探测 端口扫描 版本检测 系统检测 支持探测脚本的编写 Nmap在实际中应用场合如下: ...
- ArcGIS “Error HRESULT E_FAIL has been returned from a call to a COM component.” 异常的解决
错误提示内容: {System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been ret ...
- Java学习笔记三.3
9.异常处理:Java中的异常处理对象就是将以前的if语句进行的判断进行抽象化,并形成的一套错误处理体系.最顶端是Throwable,接着是Error,Exception,其中Exception又明显 ...
- (转)修改 ubuntu 默认启动项
转自: http://jingyan.baidu.com/article/afd8f4de58959134e386e969.html 当我们安装windows和ubuntu双系统以后,默认启动变成ub ...
- 六、Docker+Gitlab
原文:六.Docker+Gitlab (1)下载镜像: docker pull gitlab/gitlab-ce (2)运行镜像: GITLAB_HOME=`pwd`/data/gitlab dock ...
- windows服务插件利器-新生命组件XAgent使用心得
1.简单介绍 XAgent为大石头带领下的新生命团队自己开发的一个.Net下的常用的Windows服务管理组件利器,通过在控制台中简单的输入1,2,3,4,5等数字可以实现一步安装.卸载Windows ...