浅析Binder--源码系列
前言
看了很多关于Binder的文章,但是自己还是没有一个整体的概念,在这里学习和整理一下Binder的相关知识,为了给自己一个整体的印象,在这里记录一下。https://juejin.im/post/5ed64bbde51d4578732e75a1
目录Binder是什么
IPC
Binder是Android的一种跨进程方式,该通信方式在linux中是没有的。
Android Driver
Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,驱动层位于Linux内核中,它提供了最底层的数据传递,对象标识,线程管理,调用过程控制等功能。驱动层是整个Binder机制的核心
Android Framework
Binder是创建Service Manager以及BpBinder/BBinder模型,搭建与binder驱动的桥梁
Android 应用层
Binder是客户端和服务端进行通信的媒介,当bindService的时候,服务端会返回一个包含了服务端业务调用的 Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务
Binder机制说明
原理图
角色说明
- 用户进程:使用服务的进程
- 服务进程:提供服务的进程
- Service Manager进程:管理服务的注册和查询
- Binder驱动:一种虚拟设备驱动,可以连接用户和服务,ServiceManager进程。
步骤说明
- 注册服务
- 服务进程向Binder进程发起服务注册
- Binder驱动将注册请求转发给ServiceManager进程
- ServiceManager进程添加这个服务进程
- 获取服务
- 用户进程向Binder驱动发起获取服务的请求,传递要获取的服务名称
- Binder驱动将该请求转发给ServiceManager进程
- ServiceManager进程查到到用户进程需要的服务进程信息
- 最后通过Binder驱动将上述服务信息返回个用户进程
- 使用服务
- Binder驱动为跨进程通信准备:实现内存映射
- 用户进程将参数数据发送到服务进程
- 服务进程根据用户进程要求调用目标方法
- 服务进程将目标方法的结果返回给用户进程
使用服务的流程图
Binder实现原理
注册服务
Server进程创建一个Binder对象,注册后,Binder驱动持有Server进程创建的Binder实体
获取服务
Client通过bindService()绑定Server进程中注册的Server进程;用Server进程的onBind()得到创建的Binder对象的代理对象:BinderProxy对象;Client进程通过调用onServiceConnected获得了Server进程创建的Binder对象的代理对象BinderProxy对象;
使用服务
- Binder驱动实现内存映射:调用了mmap()
- Client进程发数据到Server进程:
- Client进程将需要传送的数据写入到Parcel对象中
- 通过调用代理对象的transact()将上述数据发送到Binder驱动
- Binder驱动根据代理对象找到对应的真身Binder对象所在的Server进程(自动执行)
- Binder驱动把数据发送到Server进程中,并通知Server进程执行解包(自动执行)
- 收到Binder驱动通知后,Server进程通过回调Binder对象onTranscat()进行数据解包,调用目标方法,最终将结果返回(写入reply参数中)
- 将结果返回给Client进程
- Binder驱动根据代理对象原路将结果返回并通知Client进程获取返回结果
- 通过代理对象获取reply参数,从而接收结果(之前被挂起的线程被唤醒)
Binder源码分析
架构图Binder驱动
- binder_init():驱动设备的初始化
- binder_open():打开binder驱动设备
- binder_mmap():首先在内核虚拟地址空间,申请一块与用户虚拟内存相同大小的内存;然后再申请1个page大小的物理内存,再将同一块物理内存分别映射到内核虚拟地址空间和用户虚拟内存空间,从而实现了用户空间的Buffer和内核空间的Buffer同步操作的功能。
- binder_ioctl():数据操作
- Binder在进程间数据通信的流程:当Client端与Server端发送数据时,Client(作为数据发送端)先从自己的进程空间把IPC通信数据copy_from_user拷贝到内核空间,而Server端(作为数据接收端)与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量,即可获悉内存地址,整个过程只发生一次内存拷贝
ServiceManager
启动
binder_open()打开binder驱动
- open("/dev/binder) 通过系统调用陷入内核,打开Binder设备驱动
- ioctl() 通过系统调用,ioctl获取binder版本信息
- mmap() 通过系统调用,mmap内存映射
binder_become_context_manager() 注册成为binder服务的大管家
ioctl() 成为上下文的管理者,整个系统中只有一个这样的管理者。 通过ioctl()方法经过系统调用,对应于Binder驱动层的binder_ioctl()方法
binder_loop() 进入无限循环,处理client端发来的请求
获取
概述: 获取Service Manager是通过defaultServiceManager()方法来完成,当进程注册服务(addService)或 获取服务(getService)的过程之前,都需要先调用defaultServiceManager()方法来获取gDefaultServiceManager对象。对于gDefaultServiceManager对象,如果存在则直接返回;如果不存在则创建该对象,创建过程包括调用open()打开binder驱动设备,利用mmap()映射内核的地址空间
defaultServiceManager
- ProcessState::self() :用于获取ProcessState对象(也是单例模式),每个进程有且只有一个ProcessState对象,存在则直接返回,不存在则创建
- getContextObject():用于获取BpBinder对象,对于handle=0的BpBinder对象,存在则直接返回,不存在才创建
- interface_cast():用于获取BpServiceManager对象
do_add_service() 注册服务
- svc_can_register() 检查权限,检查selinux权限是否满足
- find_svc() 服务检索,根据服务名来查询匹配的服务
- svcinfo_death() 释放服务,当查询到已存在同名的服务,则先清理该服务信息,再将当前的服务加入到服务列表svclist
do_find_service() 查询服务
find_svc() 从svclist服务列表中,根据服务名遍历查找是否已经注册。当服务已存在svclist,则返回相应的服务名,否则返回NULL
framework层分析
初始化
startReg
在Android系统开机过程中,Zygote启动时会有一个虚拟机注册过程,该过程调用AndroidRuntime::startReg方法来完成jni方法的注册。
register_android_os_Binder
- 注册Binder:建立了Binder类在Native层与framework层之间的相互调用的桥梁
- 注册BinderInternal:建立了BinderInternal类在Native层与framework层之间的相互调用的桥梁
- 注册BinderProxy:建立了BinderProxy类在Native层与framework层之间的相互调用的桥梁
注册服务
ServiceManager中addService()
获取服务
ServiceManager中getService()
最后放上一张类图
更多相关文章
- tcping测试服务器TCP端口
- Android的DDMS中的Threads的各个字段的含义
- 可以显示九天天气情况的天气预报哦-LINUX下JAVA自制服务器端,申请
- android debug 研究
- android 6.0的DozeMode低功耗模式 及 引起的进程保活问题
- [置顶] android下调试声卡驱动之wm8960介绍一
- Android(安卓)App驱动Arduino通过蓝牙控制交流调光器
- Android多进程Process开发总结-优点与缺陷
- android java进程管理(六)之apk进程的回收