SharedMemory用来实现共享内存操作很方便,也提供了获取文件描述符的方法,但是是hide的,普通app不能访问,
java
/**
* Returns the backing {@link FileDescriptor} for this SharedMemory object. The SharedMemory
* instance retains ownership of the FileDescriptor.
*
* This FileDescriptor is interoperable with the ASharedMemory NDK APIs.
*
* @return Returns the FileDescriptor associated with this object.
*
* @hide Exists only for MemoryFile interop
*/
public @NonNull FileDescriptor getFileDescriptor() {
return mFileDescriptor;
}
/**
* Returns the backing native fd int for this SharedMemory object. The SharedMemory
* instance retains ownership of the fd.
*
* This fd is interoperable with the ASharedMemory NDK APIs.
*
* @return Returns the native fd associated with this object, or -1 if it is already closed.
*
* @hide Exposed for native ASharedMemory_dupFromJava()
*/
@UnsupportedAppUsage(trackingBug = 171971817)
public int getFd() {
return mFileDescriptor.getInt$();
}
可以使用反射区获取fd,但是不够优雅,这里看看另外一个方式,通过parcel处理去间接的获取。
java
Parcel pData = Parcel.obtain();
sharedMemory.writeToParcel(pData, 0);//Parcelable.PARCELABLE_WRITE_RETURN_VALUE
//here
pData.setDataPosition(0);
ParcelFileDescriptor parcelFileDescriptor = pData.readFileDescriptor();
这样就可以获取到文件描述符了,注意,pData.setDataPosition(0);是必须的。
在 Android 中,SharedMemory(共享内存)是一种允许不同进程共享同一块内存区域的机制,常用于高效传输大量数据(如图像、视频等)。以下是其核心要点:
1. 核心概念
-
作用:避免传统 IPC(如 Binder)的数据拷贝开销,实现跨进程高效数据共享。
-
底层机制 :基于 Ashmem(Android Shared Memory Driver),一种 Linux 匿名共享内存的优化版本,支持内存区域的动态清理和权限控制。
2. 关键类与 API
-
SharedMemory
类(API 26+):封装了 Ashmem 的操作,提供创建、映射和管理共享内存的方法。 -
ParcelFileDescriptor
:用于跨进程传递共享内存的文件描述符(FD)。 -
MemoryFile
类(旧版 API 的替代):基于 Ashmem,适用于 API 较低的场景。
3. 使用步骤
创建与映射共享内存
kotlin
复制
// 1. 创建 SharedMemory 实例
val sharedMemory = SharedMemory.create("my_shmem", 1024)
// 2. 映射到当前进程内存(可读写)
val buffer = sharedMemory.mapReadWrite()
// 3. 写入数据
buffer.putInt(0, 42) // 示例:在位置 0 写入 Int 值
// 4. 跨进程传递 FD
val pfd = ParcelFileDescriptor.fromFd(sharedMemory.fileDescriptor)
// 通过 Intent/Bundle/AIDL 传递 pfd 给其他进程
其他进程访问共享内存
kotlin
复制
// 1. 接收 ParcelFileDescriptor(假设通过 Binder 传递)
val pfd: ParcelFileDescriptor = ...
// 2. 通过 FD 创建 SharedMemory
val sharedMemory = SharedMemory.createFromFd(pfd)
// 3. 映射内存(根据权限选择只读/读写)
val buffer = sharedMemory.mapReadOnly()
// 4. 读取数据
val value = buffer.getInt(0) // 读取位置 0 的 Int 值
// 5. 使用后清理
sharedMemory.unmap(buffer)
sharedMemory.close()
4. 注意事项
-
同步问题:共享内存无内置同步机制,需自行处理(如使用锁、信号量等)。
-
内存泄漏 :确保及时调用
unmap()
和close()
释放资源。 -
兼容性 :
SharedMemory
需 API 26+,低版本可使用MemoryFile
。 -
权限控制 :通过
setProtect()
设置读写权限(如Protection.READ
)。
5. 使用场景
-
高性能数据传输:如图像处理、音视频编解码、游戏资源加载。
-
跨进程大数据共享:替代 Binder 的 1MB 限制,避免序列化开销。
6. 对比其他 IPC
机制 | 性能 | 数据大小限制 | 复杂度 |
---|---|---|---|
Binder | 中 | 1MB | 低 |
文件/ContentProvider | 低 | 无 | 中 |
SharedMemory | 高 | 无 | 高 |
7. 代码示例(跨进程传递 FD)
发送端
val sharedMemory = SharedMemory.create("image_buffer", 1024 * 1024)
val pfd = ParcelFileDescriptor.fromFd(sharedMemory.fileDescriptor)
val intent = Intent().apply { putExtra("shared_fd", pfd) }
startActivity(intent)
接收端
val pfd = intent.getParcelableExtra<ParcelFileDescriptor>("shared_fd")
val sharedMemory = SharedMemory.createFromFd(pfd)
val buffer = sharedMemory.mapReadWrite()
// 处理数据...
通过合理使用 SharedMemory
,可以显著优化 Android 中跨进程的大数据交互性能,但需注意同步和资源管理。
参考资料: