阅读 1467

浅析Binder--《源码系列》

前言

看了很多关于Binder的文章,但是自己还是没有一个整体的概念,在这里学习和整理一下Binder的相关知识,为了给自己一个整体的印象,在这里记录一下。

目录
目录

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进程:
    1. Client进程将需要传送的数据写入到Parcel对象中
    2. 通过调用代理对象的transact()将上述数据发送到Binder驱动
    3. Binder驱动根据代理对象找到对应的真身Binder对象所在的Server进程(自动执行)
    4. Binder驱动把数据发送到Server进程中,并通知Server进程执行解包(自动执行)
  • 收到Binder驱动通知后,Server进程通过回调Binder对象onTranscat()进行数据解包,调用目标方法,最终将结果返回(写入reply参数中)
  • 将结果返回给Client进程
    1. Binder驱动根据代理对象原路将结果返回并通知Client进程获取返回结果
    2. 通过代理对象获取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()

最后放上一张类图 类图

文章分类
Android
文章标签