摘要:本节主要来进行Android10.0 HwBinder的原理总结linux
阅读本文大约须要花费14分钟。设计模式
文章首发微信公众号:IngresGe缓存
专一于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!服务器
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析微信
[Android取经之路] 系列文章:网络
《系统启动篇》架构
《日志系统篇》源码分析
《Binder通讯原理》:spa
《HwBinder通讯原理》.net
HwBinder的通讯原理基本上都已经说完,这一节咱们作一个简单的概要总结。
下图中涉及到HwBinder模型的4类角色:HwBinder驱动,HwServiceManager,Server和Client。Binder机制的目的是实现IPC(Inter-Process Communication),即Client和Server之间的通讯。
其中Server,Client,HwServiceManager运行于用户空间,HwBinder驱动运行于内核空间。这四个角色的关系和互联网相似:Server是服务器,Client是客户终端,HwServiceManager是域名服务器(DNS),驱动是路由器。
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。
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队列有新的请求到来时便会唤醒,若是是由所需进程唤醒的,那么进程会让其中一个线程处理响应的请求,其余线程再次进入休眠状态。
Android9.0及以后的协议码流程:
Android作了deferred_thread_work,延迟 TRANSACTION_COMPLETE,所以不会当即返回到用户空间;这容许目标进程当即开始处理此事务,从而减小延迟。而后,当目标回复(或出现错误)时,咱们将返回TRANSACTION_COMPLETE。
HwServiceManager做为HwBinder的守护进程,主要做用就是收集各个硬件服务,当有进程须要服务时由 HwServiceManager 提供特定的硬件服务。
这些硬件服务,就是咱们常说的HIDL服务,这些服务被注册到HwServiceManger的mServiceMap 这个map列表中,当有Client须要获取服务对象时,就从该map中取出HIDL服务的对象,进行转换供Client使用。
HwServiceManager中hidl服务的管理map:
在IDemo的HIDL服务和client调用过程当中,IDemo的服务为Server端,Client为客户端。
JAVA层 Client和Server的对象转换以下图所示:
IDemo服务端接收到CLient的请求后,根据下图的流程,最终流转到服务实体的onTransact()中,对解析出来的Parcel数据进行处理。
个人微信公众号:IngresGe