HwBinder入门篇-Android10.0 HwBinder通信原理(一)

摘要:本节主要来讲解Android10.0 HwBinder的通信原理概要

阅读本文大约需要花费18分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

  1. Android系统架构
  2. Android是怎么启动的
  3. Android 10.0系统启动之init进程
  4. Android10.0系统启动之Zygote进程
  5. Android 10.0 系统启动之SystemServer进程
  6. Android 10.0 系统服务之ActivityMnagerService
  7. Android10.0系统启动之Launcher(桌面)启动流程
  8. Android10.0应用进程创建过程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及启动流程
  10. Android 10.0 PackageManagerService(二)权限扫描
  11. Android 10.0 PackageManagerService(三)APK扫描
  12. Android 10.0 PackageManagerService(四)APK安装流程

《日志系统篇》

  1. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
  2. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
  3. Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
  4. Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入门篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++实例分析
  5. Android10.0 Binder通信原理(五)-Binder驱动分析
  6. Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
  7. Android10.0 Binder通信原理(七)-Framework binder示例
  8. Android10.0 Binder通信原理(八)-Framework层分析
  9. Android10.0 Binder通信原理(九)-AIDL Binder示例
  10. Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
  11. Android10.0 Binder通信原理(十一)-Binder总结

    在前面我们写了一个《Binder通信原理》的系列文章,这次准备来写一写HwBinder的系列文章。

    HAL binder是Android O(8.0)专门用于HAL(Hardware Abstract Layer)层(native)进程与其clients之间的通信机制(clients可以是native进程,也可以是Java Framework进程)。HAL binder替代了早先使用的socket通信,其kernel层实际是基于原有的binder驱动,但为了配合Client与Server之间的数据传输,需要使用特定的中间层HIDL来进行接口与数据的转换。那么,相对之前的HAL通信方式(socket),基于HIDL的HAL通信有什么优势?从系统架构的角度,HIDL为客户端与服务端提供了清晰的接口;从效率的角度,binder IPC实际在传输数据上只有一次拷贝,而socket实际传输需要两次数据拷贝。

1.概述

    在Android 8.0 之前,Binder机制比较简单,只有一个驱动设备"/dev/binder",一个守护进行"/system/bin/servicemanager",一个binder库"/system/lib64/libbinder.so".

    在Android 8.0开始,Android引入了Treble的机制,为了方便Android系统的快速移植、升级,提升系统稳定性,Binder机制被拓展成了

"/dev/binder", "/dev/hwbinder","/dev/vndbinder"。

    我们原先使用的"/dev/binder",成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。供应商进程可以访问 /dev/hwbinder,但必须将其 AIDL 接口转为使用 HIDL。

对于想要继续在供应商进程之间使用 AIDL 接口的供应商,需要使用 /dev/vndbinder(而非 /dev/binder)。

    Android8.0及之后的Binder域如下图所示:

2.HwBinder 框架

 Binder和HwBinder的一些差异
 Binder          -> HwBinder
 BpProxy          -> BpHwBinder
 BBinder           -> BHwBinder
 JavaBBinder         -> JHwBinder
 BinderProxy.java     -> HwRemoteBinder.java
 Binder.java          -> HwBinder.java

 HwBinder架构如下图所示:

在Android 8.0之前,Android Framework与Android HAL是打包成一个system.img的,而且Framework与HAL之间是紧耦合的,HAL是一个个的.so库,库和framework位于同一个进程。

Android8.0之前 的系统框架当中framework与HAL之间的一般架构框架是:

     在上图的这种架构中,每次Android的Framework进行升级时,对应的HAL层都需要跟着升级,费时费力,这也Android最新版本推广较慢的原因。

    在Android 8.0及之后,Android觉得这也不行,每次出了新版本,但是用的人很少,得让大家快速使用新版本。于是Android引入了一个Treble的架构,把vendor的一些功能和库与system进行分离,OEM厂商设计的内容都放到vendor中去,Android原生的放到system中,这样Android只要升级System就能快速完成版本的升级,在这个场景下,Android Framework放在了System空间,厂商的HAL库放在了Vendor空间,两者之间使用hwbinder进行通信,通信的接口语言为HIDL。

    Android8.0及之后 的系统框架当中framework与HAL之间的一般架构框架是:

 下图展示了Android 有Treble和没有Treble的升级方式:

3.Hwbinder 与Binder的区别

3.1 Binder

    在Android 8.0之前,这是我们最熟悉也一直使用的Binder。Java层继承Binder,Native C/C++层继承Bbbinder,然后通过servicemanager进程注册实名Binder,然后通过已经创建好的Binder接口传递匿名Binder对象,拿到BinderProxy或者BpBinder以后,就可以Binder通信了。

在Android 8.0后,这个Binder机制继续保留,/dev/binder 设备节点成为框架进程的专有节点,这意味着供应商进程无法再访问此节点。

    如果你是系统厂商,在system分区有进程,/dev/biner机制还是可以继续使用,但是你的进程在vendor分区,那只能使用/dev/hwbinder 或者/dev/vndbinder.

    Binder机制需要两个进程都同属于System分区

3.2 HwBinder

    hwbinder和 binder不同,hwbinder是一套全新的流程,有单独的驱动设备"/dev/hwbinder",独立的守护进程"hwservicemanager",独立的SDK-"libhwbinder"

HwBinder机制可以跨System和Vendor分区使用

4. 为什么要引入hwbinder

    Android 8.0中引入了Treble机制,Treble 项目通过将底层供应商实现从 Android 内核框架中剥离出来,使Android更新变得更简单。这种模块化的设计允许分别独立更新平台和供应商提供的组件。让更新变得更轻松、更快速,然而,Treble 加强模块化设计还有一个目的:提高安全性。

    Treble引入后,新增了一个vendor.img, 即原先的system分区,被拆分为了system分区和vendor分区,soc及供应商的功能实现都需要放到vendor分区,这样将system和vendor相关的镜像分开,便于能方便地更新和升级system,并且不依赖vendor等底层。

    在Android 8.0之前,HAL是一个个的.so库,通过dlopen来进行打开,库和framework位于同一个进程, 在此之前的Android 系统架构当中,Android Framework 与Android HAL是打包成一个system.img的,而且Framework 与HAL之间是紧耦合的,通过链接的方式使用相应的硬件相关so库。

Android 8.0之前的通信机制如下图所示:

所以每次Android framework的升级需要对应的Android HAL升级,这需要供应商花费很多的人力去升级相应的 Vendor HAL Implemetation,这也就是导致Android版本升级很缓慢,很多用户几年之后,Android都不能得到及时更新。

    在Android8.0及以后的版本中,Android设计了一套新的机制来隔离HAL层,引入了一个HIDL的语言来定义Framework和HAL之间的接口

    在Android 8.0以及以后的版本当中,Android 更新了新的框架设计在新的框架设计当中,引入了一套叫HIDL的语言来定义Freamework与HAL之间的接口,Android Framework会在system分区当中,而VendorHAL Implemetation会在一个新定义的分区(Vendor.img)当中,这样刷新的system.img 才不会影响到Vendor HAL Implemetation。

    在Android 8.0及之后,HAL库和framework不在同一个进程,他们之间使用hwbinder进行进程间通信。

    Android 8.0引入Treble后,各层的通信机制如下:

5.HwBinder的通信原理

 HwBinder 通信采用 C/S 架构,从组件视角来说,包含 Client、 Server、 HwServiceManager 以及 HwBinder 驱动,其中 HwServiceManager 用于管理系统中的各种服务。

HwBinder 在 framework 层进行了封装,通过 JNI 技术调用 Native(C/C++)层的 HwBinder 架构。

 HwBinder 在 Native 层以 ioctl 的方式与 Binder 驱动通讯。

 HwBinder通信原理图如下:

HwBinder通信流程如下:

  1. 首先服务端需要向HwServiceManager进行服务注册,HwServiceManager有一个全局的service列表mServiceMap,用来缓存所有服务的对象和name。

  2. 客户端与服务端通信,需要拿到服务端的对象,由于进程隔离,客户端拿到的其实是服务端的代理,也可以理解为引用。客户端通过HwServiceManager从mServiceMap中查找服务,HwServiceManager返回服务的代理。

  3. 拿到服务对象后,我们需要向服务发送请求,实现我们需要的功能。通过 BpHwBinder 将我们的请求参数发送给 内核,通过共享内存的方式使用内核方法 copy_from_user() 将我们的参数先拷贝到内核空间,这时我们的客户端进入等待状态。然后 Binder 驱动向服务端的 todo 队列里面插入一条事务,执行完之后把执行结果通过 copy_to_user() 将内核的结果拷贝到用户空间(这里只是执行了拷贝命令,并没有拷贝数据,binder只进行一次拷贝),唤醒等待的客户端并把结果响应回来,这样就完成了一次通讯。

    在这里其实会存在一个问题,Client和Server之间通信是称为进程间通信,使用了HwBinder机制,那么Server和HwServiceManager之间通信也叫进程间通信,Client和Server之间还会用到HwServiceManager,也就是说HwBinder进程间通信通过HwBinder进程间通信来完成,这就好比是 孵出鸡前提却是要找只鸡来孵蛋,这是怎么实现的呢?

    HwBinder的实现比较巧妙:预先创造一只鸡来孵蛋:HwServiceManager和其它进程同样采用HwBinder通信,HwServiceManager是Server端,有自己的HwBinder对象(实体),其它进程都是Client,需要通过这个HwBinder的引用来实现HwBinder的注册,查询和获取。

    HwServiceManager提供的HwBinder比较特殊,它没有名字也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR_EXT命令将自己注册成HwServiceManager时HwBinder驱动会自动为它创建HwBinder实体(这就是那只预先造好的鸡)。

    其次这个HwBinder的引用在所有Client中都固定为0(handle=0)而无须通过其它手段获得。也就是说,一个Server若要向HwServiceManager注册自己HwBinder就需要通过0这个引用号和HwServiceManager的Binder通信。

    类比网络通信,0号引用就好比域名服务器的地址,你必须预先手工或动态配置好。要注意这里说的Client是相对HwServiceManager而言的,一个应用程序可能是个提供服务的Server,但对HwServiceManager来说它仍然是个Client。

    

/system/tools/hidl/

根据HAL接口 .hal来产生相应的Proxy(client端接口)以及stub(server端接口)

/system/libhidl

HIDL状态与HAL服务管理接口

/hardware/interfaces/

各个模块HAL层接口,每个模块都包含了一个Android.bp的脚步来生成对应的代理(Proxy)与存根对象(stub),如radio接口IRadio.hal,sensors接口ISensors.hal

android_os_HwBinder.java\cpp (JNI)

Java层HAL binder的JNI代码,负责将Java层的请求传递给相应的server进程

/dev/hwbinder

/kernel/msm-4.9/drivers/android/binder.c

/kernel/msm-4.9/drivers/android/binder_alloc.c

hwservicemanager

/system/hwservicemanager/hwservicemanager.rc

/system/hwservicemanager/ServiceManager.cpp

/system/hwservicemanager/HidlService.cpp

/system/hwservicemanager/HidlService.h

libhwbinder

/system/libhwbinder/Binder.cpp

/system/libhwbinder/BpHwBinder.cpp

/system/libhwbinder/IInterface.cpp

/system/libhwbinder/IPCThreadState.cpp

/system/libhwbinder/ProcessState.cpp

/system/libhwbinder/Parcel.cpp

/system/libhwbinder/include/hwbinder/Binder.h

/system/libhwbinder/include/hwbinder/BpHwBinder.h

/system/libhwbinder/include/hwbinder/IBinder.h

/system/libhwbinder/include/hwbinder/IInterface.h

/system/libhwbinder/include/hwbinder/IPCThreadState.h

/system/libhwbinder/include/hwbinder/ProcessState.h

/system/libhwbinder/include/hwbinder/Parcel.h

7.总结

  Android引入Treble机制后,扩展了一个vendor分区,为了能够快速的进行升级,做了隔离HAL层的机制,为了System/System、System/Vendor、Vendor/Vendor 之间进行不同的进程间通信,把原有的Binder机制拆分成了Binder、HwBinder、VndBinder。

Binder和VndBinder 共用一套libbinder、servicemanager的代码,使用AIDL接口,两者不能共存。

  HwBinder采用了单独的libhwbinder、hwservicemanager的代码,单独管理,使用HIDL接口。

  三者之间互不干扰,在方便系统升级的同时,又提升了系统的安全和稳定性。

参考:

《Android Treble Architecture: Part 3 - Changes for Treble[Binder & ServiceManager]》

我的微信公众号:IngresGe

猜你喜欢

转载自blog.csdn.net/yiranfeng/article/details/107751217
今日推荐