HwBinder原理总结-Android10.0 HwBinder通信原理(十一)

1 概述
       HwBinder的通信原理基本上都已经说完,这一节我们做一个简单的概要总结。

2 HwBinder通信模型
       下图中涉及到HwBinder模型的4类角色:HwBinder驱动,HwServiceManager,Server和Client。Binder机制的目的是实现IPC(Inter-Process Communication),即Client和Server之间的通信。

       其中Server,Client,HwServiceManager运行于用户空间,HwBinder驱动运行于内核空间。这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,HwServiceManager是域名服务器(DNS),驱动是路由器。

 

3 HwBinder的架构

 

4 HwBinder的通信原理

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

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

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

       

 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。


 
5 HwBinder传输过程
  Binder-IPC机制,就是指在进程间传输数据(binder_transaction_data),一次数据的传输,称为事务(binder_transaction)。

  对于多个不同进程向同一个进程发送事务时,这个同一个进程或线程的事务需要串行执行,在HwBinder驱动中为binder_proc和binder_thread都有todo队列。

  也就是说对于进程间的通信,就是发送端把binder_transaction节点,插入到目标进程或其子线程的todo队列中,等目标进程或线程不断循环地从todo队列中取出数据并进行相应的操作。

 

 在Binder驱动层,每个接收端进程都有一个todo队列,用于保存发送端进程发送过来的binder请求,这类请求可以由接收端进程的任意一个空闲的binder线程处理。

  接收端进程存在一个或多个binder线程,在每个binder线程里都有一个todo队列,也是用于保存发送端进程发送过来的binder请求,这类请求只能由当前binder线程来处理。

  binder线程在空闲时进入可中断的休眠状态,当自己的todo队列或所属进程的todo队列有新的请求到来时便会唤醒,如果是由所需进程唤醒的,那么进程会让其中一个线程处理响应的请求,其他线程再次进入休眠状态。

6 HwBinder协议码流程
  Android9.0及之后的协议码流程:

  Android做了deferred_thread_work,延迟 TRANSACTION_COMPLETE,因此不会立即返回到用户空间;这允许目标进程立即开始处理此事务,从而减少延迟。然后,当目标回复(或出现错误)时,我们将返回TRANSACTION_COMPLETE。

 

7.HwServiceManager的服务管理
  HwServiceManager作为HwBinder的守护进程,主要作用就是收集各个硬件服务,当有进程需要服务时由 HwServiceManager 提供特定的硬件服务。

  这些硬件服务,就是我们常说的HIDL服务,这些服务被注册到HwServiceManger的mServiceMap 这个map列表中,当有Client需要获取服务对象时,就从该map中取出HIDL服务的对象,进行转换供Client使用。

  HwServiceManager中hidl服务的管理map:

 

8 Native层HIDL服务与Client交互流程
    在IDemo的HIDL服务和client调用过程中,IDemo的服务为Server端,Client为客户端。

 

9 JAVA层HIDL服务与Client交互流程
  JAVA层 Client和Server的对象转换如下图所示:

 

  IDemo服务端接收到CLient的请求后,根据下图的流程,最终流转到服务实体的onTransact()中,对解析出来的Parcel数据进行处理。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值