当前位置: 首页 > news >正文

【Android】SharedMemory获取文件描述符

SharedMemory用来实现共享内存操作很方便,也提供了获取文件描述符的方法,但是是hide的,普通app不能访问,

    /**
     * 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处理去间接的获取。

            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

机制性能数据大小限制复杂度
Binder1MB
文件/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 中跨进程的大数据交互性能,但需注意同步和资源管理。

参考资料:

https://blog.51cto.com/u_16213375/11974814

相关文章:

  • 《熔化焊接与热切割作业》备考建议
  • 怎么把 GitHub 中的 R 包项目手动安装到 conda 环境中?
  • C++ 初阶总复习 (持续更新)
  • C++11中引入的比较常用的新特性讲解(上)
  • 如何改掉经常说“然后”、“就是”、“嗯”的毛病
  • 解决Compose编译报错问题 couldn‘t find inline method Landroidx/compose/...
  • arm对应hex_ASCII与HEX对照转换表
  • 程序化广告行业(34/89):移动端特色广告与创意策略探秘
  • Uncert-CoT: 计算不确定性判断是否启用CoT
  • Slidev使用(一)安装
  • MySQL的sql语句后/G是什么作用?
  • Mysql增删改查
  • 怎样实现CAN数据的接收和发送?
  • 基于Python的3D贴图制作技术研究与实践
  • 数据库基础知识点(系列五)
  • 深入了解 Git Merge:用法、类型与合并冲突处理
  • GPT Researcher 的win docker安装攻略
  • Postman 下载文件指南:如何请求 Excel/PDF 文件?
  • 递归、搜索与回溯第四讲:floodfill算法
  • ​macro-F1(宏平均F1)​和micro-F1(微平均F1)
  • 第32届梅花奖终评启幕,上海京剧院《智取威虎山》满堂彩
  • 马上评|比余华与史铁生的友情更动人的是什么
  • 老铺黄金拟配售募资近27亿港元,用于门店拓展扩建及补充流动资金等
  • 巴基斯坦信德省卡拉奇发生爆炸
  • 上海一中院一审公开开庭审理被告人胡欣受贿案
  • 自然资源部印发地理信息数据分类分级指南