android共享内存(ShareMemory)的实现
Android 几种进程通信方式
跨进程通信要求把方法调用及其数据分解至操作系统可以识别的程度,并将其从本地进程和地址空间传输至远程进程和地址空间,然后在远程进程中重新组装并执行该调用。
然后,返回值将沿相反方向传输回来。
Android 为我们提供了以下几种进程通信机制(供开发者使用的进程通信 API)对应的文章链接如下:
•文件
•AIDL (基于 Binder)
•Binder
•Messenger (基于 Binder)
•ContentProvider (基于 Binder)
•Socket
在上述通信机制的基础上,我们只需集中精力定义和实现 RPC 编程接口即可。
如何选择这几种通信方式
这里再对比总结一下:
•只有允许不同应用的客户端用 IPC 方式调用远程方法,并且想要在服务中处理多线程时,才有必要使用 AIDL
进程通信方式
•如果需要调用远程方法,但不需要处理并发 IPC,就应该通过实现一个 Binder 创建接口
•如果您想执行 IPC,但只是传递数据,不涉及方法调用,也不需要高并发,就使用 Messenger 来实现接口
•如果需要处理一对多的进程间数据共享(主要是数据的 CRUD),就使用 ContentProvider
•如果要实现一对多的并发实时通信,就使用 Socket 
image.png
IPC分析:
android IPC的核心方式是binder,但是android binder的传输限制1M(被很多进程共享),在较大数据交换一般通过文件,但是效率很低,因此介绍下新的内存共享方式: ShareMemory
具体实现:
通过binder把MemoryFile的ParcelFileDescriptor 传到Service; 在服务端通过ParcelFileDescriptor 读取共享内存数据;
•客户端 LocalClient.java 通过MemoryFile获取ParcelFileDescriptor,通过Binder把ParcelFileDescriptor(int类型)传递到服务端
•服务端 RemoteService 获取到ParcelFileDescriptor 之后,有两种方式 第一种:通过FileInp
utStream 读取ParcelFileDescriptor 的FD,此种方式的问题在于,每次读取之后FD的游标都在文件最后(也就是说第二次读取结果是不低的,必须重置FD的游标) 第二种:就是通过反射,直接ParcelFileDescriptor构建MemoryFile,然后读取,此种方式问题在于26和27实现的不同,代码如下:
Android P(9.0)反射限制: 上述反射的方式在android P上被限制(android 9.0禁止通过放射调用系统的的非公开方法),此路不同(If they cut off one head, two more shall take it' Hail Hydra.),还有千万条路
•ShareMemory android O(8.0)之后增加新的共享内存方式,SharedMemory.java 此类继承Parcelable,可以作为IPC通讯传输的数据;
•ClassLoader 多态:此方式并非真正的多态,而是根据ClassLoader类的加载顺序,在应用中构建一个和系统类同样包名的类(方法也同名,可以不做实现),编译时使用的应用中的类,运行时加载的是系统中的类,从而实现伪多态;
GitHub:
ShareMemory优点:
binder 限制(binder的android上的限制1M,而且是被多个进程共享的); binder 在android进程中经过一次内存copy,内存共享通过mmap,0次copy效率更高;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。