导航:首页 > 操作系统 > androidnative方法

androidnative方法

发布时间:2023-08-18 01:07:52

android通信方式篇(七)-Binder机制(Native层(下))

本篇文章针对向ServiceManager注册服务 和 获取服务两个流程来做总结。在这两个过程中,ServiceManager都扮演的是服务端,与客户端之间的通信也是通过Binder IPC。

在此之前先了解下Binder的进程与线程的关系:

用户空间 :ProcessState描述一个进程,IPCThreadState对应一个进程中的一个线程。
内核空间 :binder_proc描述一个进程,统一由binder_procs全局链表保存,binder_thread对应进程的一个线程。
ProcessState与binder_proc是一一对应的。

Binder线程池 :每个Server进程在启动时会创建一个binder线程池,并向其中注册一个Binder线程;之后Server进程也可以向binder线程池注册新的线程,或者Binder驱动在探测到没有空闲binder线程时会主动向Server进程注册新的的binder线程。对于一个Server进程有一个最大Binder线程数限制15,(#define DEFAULT_MAX_BINDER_THREADS 15)。对于所有Client端进程的binder请求都是交由Server端进程的binder线程来处理的。我的理解是:binder线程是进程进行binder ipc时的一条数据处理路径。

MediaPlayerService向ServiceManager注册过程如下:

相关类:

整个过程总结如下:
1 获取BpServiceManager 与 BpBinder
由defaultServiceManager()返回的是BpServiceManager,同时会创建ProcessState对象和BpBinder对象。然后通过BpBinder执行transact,把真正工作交给IPCThreadState来处理。

2 BpBinder transact
Binder代理类调用transact()方法,真正工作还是交给IPCThreadState来进行transact工作。

3 通过IPCThreadState 包装并转换数据并进行transact事务处理
每个线程都有一个IPCThreadState,每个IPCThreadState中都有一对Parcel变量:mIn、mOut。相当于两根数据管道:

最后执行talkWithDriver。

writeTransactionData:将BC Protocol + binder_transaction_data结构体 写入mOut, 然后执行waitForResponse:

由talkWithDriver将数据进一步封装到binder_write_read结构体,通过ioctl(BINDER_WRITE_READ)与驱动通信。同时等待驱动返回的接收BR命令,从mIn取出返回的数据。

mIn包装的数据结构(注册服务handle = 0 ,code 为ADD_SERVICE_TRANSACTION):

4 Binder Driver
把binder_write_read结构体write_buffer里数据取出来,分别得到BC命令和封装好数据的事务binder_transaction_data, 然后根据handler,在当前binder_proc中,找到相应的binder_ref,由binder_ref再找到目标binder_node实体,由目标binder_node再找到目标进程binder_proc。然后就是插入数据:当binder驱动可以找到合适的线程,就会把binder_transaction节点插入到servciemanager的线程的todo队列中,如果找不到合适的线程,就把节点之间插入servciemanager的binder_proc的todo队列。

5 ServiceManager
经过Binder Driver的处理,数据已经到了ServiceManager进程,在BR_TRANSACTION的引导下,在binder_loop()中执行binder_parser()取出数据,执行do_add_service()操作,最终向 svcinfo 列表中添加已经注册的服务(没有数据的返回)。最后发送 BR_REPLY 命令唤醒等待的线程,通知注册成功。结束MediaPlayerService进程 waitForResponse()的状态,整个注册过程结束。

获取服务的过程与注册类似,首先 ServiceManager 向 Binder 驱动发送 BC_TRANSACTION 命令携带 CHECK_SERVICE_TRANSACTION 命令,同时获取服务的线程进入等待状态 waitForResponse()。Binder 驱动收到请求命令向 ServiceManager 的发送 BC_TRANSACTION 查询已注册的服务,会区分请求服务所属进程情况。

查询到直接响应 BR_REPLY 唤醒等待的线程。若查询不到将与 binder_procs 链表中的服务进行一次通讯再响应。

以startService为例来简单总结下执行流程:

3.1 从方法执行流程来看:

Client :

1 AMP.startService 标记方法以及通过Parcel包装数据;

2 BinderProxy.transact 实际调用native的 android_os_BinderProxy_transact 传递数据;

3 获取BpServiceManager 与 BpBinder 同时会创建ProcessState。然后通过BpBinder执行transact,把真正工作交给IPCThreadState来处理;

4 IPC.transact 主要执行writeTransactionData,将上层传来的数据重新包装成binder_transaction_data,并将BC Protocol + binder_transaction_data结构体 写入mOut;

5 IPC waitForResponse talkWithDriver + 等待返回数据;

6 talkWithDriver 将数据进一步封装成binder_write_read,通过ioctl(BINDER_WRITE_READ)与驱动通信;

Kernel :

7 binder ioctl 接收BINDER_WRITE_READ ioctl命令;

8 binder_ioctl_write_read 把用户空间数据ubuf拷贝到内核空间bwr;

9 binder_thread_write 当bwr写缓存有数据,则执行binder_thread_write;当写失败则将bwr数据写回用户空间并退出;

10 binder_transaction 找到目标进程binder_proc并插入数据到目标进程的线程todo队列,最终执行到它
时,将发起端数据拷贝到接收端进程的buffer结构体;

11 binder_thread_read 根据binder_transaction结构体和binder_buffer结构体数据生成新的binder_transaction_data结构体,写入bwr的read_buffer,当bwr读缓存有数据,则执行binder_thread_read;当读失败则再将bwr数据写回用户空间并退出;最后,把内核数据bwr拷贝到用户空间ubuf。

12 binder_thread_write + binder_ioctl BR命令和数据传递

Server:

13 IPC.executeCommand 解析kernel传过来的binder_transaction_data数据,找到目标BBinder并调用其transact()方法;

14 IPC.joinThreadPool 采用循环不断地执行getAndExecuteCommand()方法, 处理事务。当bwr的读写buffer都没有数据时,则阻塞在binder_thread_read的wait_event过程. 另外,正常情况下binder线程一旦创建则不会退出.

15 BBinder.transact 到Binder.exeTransact 调用 AMN.onTransact

16 AMN.onTransact 把数据传递到AMS.starService去执行

17 AMS.starService Server处理了Client的请求了

然后原路replay回去,talkWithDriver 到Kernel ,然后找到Client进程,把数据拷贝到read_buffer里,最终唤醒IPC,把反馈传递回AMP.startService。完成启动服务。

3.2 从通信协议流程来看:

非oneWay:

oneway:

oneway与非oneway区别: 都是需要等待Binder Driver的回应消息BR_TRANSACTION_COMPLETE. 主要区别在于oneway的通信收到BR_TRANSACTION_COMPLETE则返回,而不会再等待BR_REPLY消息的到来. 另外,oneway的binder IPC则接收端无法获取对方的pid.

3.3 从数据流来看

从用户空间开始:

进入驱动后:

回到用户空间:

参考:
http://gityuan.com/2016/09/04/binder-start-service/
http://gityuan.com/2015/11/28/binder-summary/
http://gityuan.com/2015/11/14/binder-add-service/
http://gityuan.com/2015/11/15/binder-get-service/

阅读全文

与androidnative方法相关的资料

热点内容
手机设置远程定位服务器地址 浏览:913
android模拟器装apk 浏览:773
炒黄金app哪个好用 浏览:993
恐惧症app哪个最好用 浏览:288
亿赛通加密软件好用吗 浏览:578
为什么光遇排队服务器忙 浏览:826
哪个app能把手p瘦 浏览:253
java中的date类型 浏览:431
面向程序员的范畴论 浏览:57
如何查询服务器所有电脑名 浏览:902
shell命令jar 浏览:301
有什么做手帐app 浏览:156
phpjquery源码 浏览:886
大话西游手游源码 浏览:655
javaudp代码 浏览:660
linuxu盘启动win7 浏览:990
如何启用交换机dhcp服务器 浏览:237
三田汽车压缩机好吗 浏览:294
马蜂窝app偏向什么客户 浏览:366
php简单的登录注册 浏览:554