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

【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


http://www.kler.cn/a/612445.html

相关文章:

  • 【Python】天气数据可视化
  • Hyperlane 似乎是一个轻量级、高性能的 Rust HTTP 服务器库
  • 弱电系统:从基础原理到家庭与小区网络部署
  • C语言 二维线性查表linearInterpolation 100行实现通用线性查表
  • 深入理解Golang标准库`testing/fstest`包的用法和技巧进行文件系统测试
  • linux之 内存管理(5)-CMA 连续内存管理器
  • 行业大数据实验报告 通过聚类算法实现睡眠健康群体的精准智能划分
  • 如何在 HTML 中使用<dialog>标签创建模态对话框,有哪些交互特性
  • Spring AOP:面向切面编程的探索之旅
  • PTA 1105-链表合并(C++)
  • SpringMVC实战——转发和重定向及实际场景
  • Dify实现自然语言生成SQL并执行
  • 高级数据结构01BST树
  • 如何使用VS中的Android Game Development Extension (AGDE) 来查看安卓 Logcat 日志
  • ‌JVM 内存模型(JDK8+)
  • 如何使用Python爬虫按关键字搜索1688商品?
  • 测谎仪策略思路
  • linux 安装open webui
  • 第二十章:类型属性的重载_《C++ Templates》notes
  • 【商城实战(80)】从0到1剖析:区块链如何重塑商城生态