一直以来,自以为对binder有所了解,也曾暗暗佩服自己怎么这么厉害。直到一次需要用到 binder 进行通信,信心百倍的提出使用 service 中 binder 或者 messager 来获取,但是原来已经使用来 contentprovider ,再使用 service 就存在延迟和重复等等问题,在想着使用 aidl (思索着还是脱离不了 service )、 contentobserver 这个到不错,但是因为需要双向通信,总不能每个进程在单独配一个独自的contentprovider 、再有就是使用广播来进行了,但是太依赖系统处理,实时性等都无法保证。
这时候有同事提出可以使用各个进程把 binder 传到 contentprovider,这样在 cp 中就可以通过 binder 调用相关回调方法实现通信,而各个进程访问 cp 即可。
第一反应,可行。可是转念一想,adil 的 stub 就只是创建一个 binder 对象、实例,传递到 cp 那边不就只是把这个对象传过去了吗,cp 对调用这个对象方法还可以在回到原进程???少了一个关键步骤啊。那就是 binder 注册哪去了,为什么传个对象过去,调用方法还可以回到原进程,不是就是在当前进程了吗?
由此我提出了强烈的质疑。binder机制分为client,server,binder 驱动,ServcieManager。ServiceManager 实质上就是 server ,来进行统一管理。那我们自己把 binder 传递过去没有意义啊。
实践出真知。我们实验下来发现是可行的。由此我反思到自己 对 binder 理解还是停留在表层啊。仔细看 messager 实际上也是差不多的情况。当时为这个情况反复查了好久的资料,终于确定 binder 驱动是关键,它负责来 binder 对象本地和远端代理的关联。Binder 实体在 Binder 驱动中的传输,会被特殊处理,如果传递到其它进程会成为代理对象,其它进程即可调用对象方法。不经过 ams 只要能通过 跨进程传递对象过去即可实现。这么看来 ServiceManager 是起到注册管理显式 binder 的作用,这样可以根据名字来做到返回对应的 binder 对象。
在期间其实生出了一个想法,如果可以存储到文件里,然后在另外进程读出来不是就可以实现自己的跨进程的目的了吗。可是很遗憾,表象上的传递只是表面,实际上它在内核层还做了不少的事情,比如 binder 支持传递文件描述符,ParcelFileDescriptor ,但是实际上是在内核为新的进程又申请了一个文件描述符来关联到文件。
binder 做为 android 底层的跨进程通信基础,是有很多细节需要注意。可能这也是编码的魅力吧。往往简单的东西下有复杂的实现,但是理解后有觉得简单,再往下又复杂。所谓的精通等等也只是建立在某个角度,某个层面。所以我们更应该锻炼自己的思维,有不断更新的架构的思维才能保证自己永不落伍