Binder学习笔记(十三)—— 小结

本文深入探讨了Android Binder机制,解释了驱动层为何篡改binder_buffer数据,分析了Server端如何组织addService数据,以及ServiceManager如何响应checkService请求。在驱动层,binder<–>handle的转换确保了跨进程调用的唯一性。此外,文章揭示了Server、ServiceManager和Client之间复杂的数据结构关系。
摘要由CSDN通过智能技术生成

驱动层为什么要篡改binder_buffer内的数据?

先给出这张图:
binder_transaction(...)完成后的数据结构
上图中标红的部分需要重点考虑,为什么驱动层要篡改这两个字段呢?我们结合前面的文章或许可以找出端倪。在Binder学习笔记(七)—— ServiceManager如何响应addService请求 ?一文中其实留下了挺多疑问。

server端调用addService(…)向ServiceManager注册该Service,ServiceManager保存Service的(name, binder)二元对以备后用,但其中最不可理解的是在函数bio_get_ref(struct binder_io *bio)中判断如果Service的type==BINDER_TYPE_HANDLE,binder为0。这个疑团现在就可以打开了:因为ServiceManager收到的service的type不可能为BINDER_TYPE_BINDER!

尽管在Server端组织的数据结构中type=BINDER_TYPE_BINDER,但在驱动层被上图的红色部分过了一手,把它改成了BINDER_TYPE_HANDLE。
也就是说在由Server端发给ServiceManager时,binder在Server一端是实体,到了ServiceManager一端就要变成引用,因为实体并不在自己的进程空间。同理,我推断当Client端调用Server端的Binder服务时,Client端使用的是引用,到了Server端会变成实体。我们看binder_transaction(...)函数中case BINDER_TYPE_HANDLE和case BINDER_TYPE_WEAK_HANDLE的代码,确实是有这样的修改。

flat_binder_object的binder字段和handle字段公用一个联合,在实体端使用binder,在引用端使用handle,在驱动层完成binder<–>handle的转换,使之对实体/引用端透明,这是驱动层的职责。那么为什么要有这种转换呢?这个字段的作用就是为了提领到binder,使用一个唯一标识不就行了么?问题就在于这个“唯一标识”不好搞,binder是跨进程的调用,所以这个“唯一标识”必须要系统全局唯一。binder在Server端就是BnService的影子对象的地址,这个地址在Server进程中是全局唯一的,但是到了ServiceManager一端却不唯一,为了确保它在这一端的唯一性,驱动为它生成了在ServiceManager中的唯一id,即hand

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值