为什么已经有了管道等跨进程通信方式,却要另外创建Binder方式?直接在原来的跨进程方式上面修改,不是更加方便吗?
跨进程通信就是两个进程之前的数据传递。
我能想到最简单的跨进程通信就是在sdcard目录下创建一个文件1.txt,然后应用A写数据,应用B读数据。
这里抽象出,任何跨进程通信绕不开的两个关键的共性问题:
例子一中数据存放区域就是磁盘
例子二中约定就是应用A写sdcard/1.txt,应用B读sdcard/1.txt
共性问题1:
进程间的内核共享内存区域
共性问题2:
由于匿名管道只能通过父进程fork子进程的时候让两个进程分别持有pipe的两端fd,然后分别读写fd进行通信,所以匿名管道不适合跨进程通信,无法通过约定让两个没有关系的进程进行跨进程通信
实名管道解决了共性问题2,如何进行简单的约定,这个约定就是约定pathname,然后分别读写。
例如应用A和应用B约定实名的管道分别是./A_B和./B_A,这样子就可以让应用A和B分别读写了。
约定某个ip地址,例如访问某个网站,就是约定dns服务器,然后访问dns服务器ip,传递网址返回要请求的ip,获得实际要访问的ip,在进行ip的访问,当然还有对应的tcp/ip的协议栈了,这些都是约定。
约定某个端口,就是类似someip的协议,约定双方要监听的端口是30490,然后具体的约定就是someip的协议和网络协议栈。
可以参考我之前的文章 https://cloud.tencent.com/developer/article/2290363
好像已经有人干了在原来的跨进程方式上面修改,然后形成跨进程通信的方案了。那就是someip,基于socket通信开发的。
前面所有讲的跨进程通信方式都是两次拷贝,需要从用户态到内核态,内核态到用户态两次数据拷贝。只有重新写驱动才能实现一次拷贝。
fd的传递不是简单的fd数字的传递,而是新的fd对应file结构体在对端关联。会有人说,那传递fd对应的文件路径,重新打开不就行了,但是此fd是linux中一切皆文件的概念,很多fd并不一定会有文件路径对应。现有的跨进程通信无法做到。而且重新打开文件路径,会创建一个新的file内核结构体,读写指针无法共享。
参考我之前的文章 https://cloud.tencent.com/developer/article/1639804
如果发现最后被请求的进程和发起请求的进程是同一个进程,如何高效的通信犹如函数调用一样。
参考我之前的文章 https://cloud.tencent.com/developer/article/1639790
如果发现A请求B,B请求C,C又请求A,如何利用A请求B时候休眠的线程进行C的响应,减少线程资源的浪费。
参考我之前的文章 https://cloud.tencent.com/developer/article/1639787
以上的几个功能都很难利用现有的跨进程通信的方式,二次开发实现,因为二次开发只能在用户态了。为什么Binder要实现上述这几个功能,我猜是因为刚开始的时候移动端性能差,内存紧张,对现有跨进程通信的性能要求高,以及大规模进程之间通信管理难度加大要求,从而萌生了重新从驱动开始写一套跨进程通信机制的想法,当然不是从零开始思考的,我认为作者在用户态的通信协议,有点参考了JavaRMI思想,因为javaRMI是在1998年发布的,Binder应该比它晚,后面2011年发布的someip我猜也或多或少借鉴了JavaRMI的思考。
因为Binder暂不支持跨芯片通信,汽车上更多的是跨设备通信和跨进程通信混合,有可能某个需求一变,原本只需要跨进程通信要变成跨芯片通信了,这样子代码就需要重新写了,如果用someip就不一样,只需要把服务部署到别的芯片,代码基本不用动,当然Binder也在慢慢支持基于网络的通信。
1.通过IBinder对象(Binder或者BinderProxy)可以调用Binder对象的接口 2.通过Binder接口可以传递基础数据,IBinder,FD 3.世界上第一个Binder对象就是SM
socket,pipe,ion可都是基于fd,Binder成为了这些跨进程通信的fd对象的媒介,从而形成了丰富多彩的跨进程通信
pipe-vsync信号
socket-inputchannel
ion-surface对应的某个buffer
本文的内容可能跳跃的比较厉害,但是其实是我对Binder通信的一些心得体会,有些内容可能你一下子无法理解,但是我相信你真的搞懂Binder后,再回过来我这篇文章,应该会认同的我的观点。
这个问题其实也没有完美的答案,有时候思考问题的过程,比得到问题的答案更重要。