HwBinder入门篇-Android10.0 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通信流程如下:

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

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

拿到服务对象后,我们需要向服务发送请求,实现我们需要的功能。通过 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接口。

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

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值