【问题标题】:Shared memory region in NDKNDK 中的共享内存区域
【发布时间】:2012-10-12 18:10:10
【问题描述】:

我想要一个从本机代码映射和访问的共享内存块(ashmem 区域)。我还希望这个块被多个应用程序使用。我还希望它在 SDK 7 级(Android 2.1)上工作

有两条路线。我可以在本机代码中创建一个 ashmem 区域;但接下来的问题是 - 我如何将整数文件描述符传递给另一个进程?您可以通过Parcel 编组FileDescriptor 对象,但无法围绕原始FD 构造一个对象。还有 ParcelFileDescriptor 支持构造和检索整数 FD,但相关方法仅在 SDK 12 级或更高级别中支持。

或者,我可以创建一个MemoryFile。有一个 fugly way 可以在 Parcels 中传递它。但是如何从中检索文件描述符,以便本机代码具有 mmap() 的内容?

【问题讨论】:

    标签: android android-ndk shared-memory parcel ashmem


    【解决方案1】:

    在从 1.5 到 4.1 的所有 Android 版本上,FileDescriptor 都有一个名为 descriptorint 数据成员。它在早期版本的 Android 上是包私有的,在最近的版本上是私有的。通过一些刻意的访问控制颠覆,您可以通过反射或通过 JNI 访问它。每个都可以绕过访问控制 - 在反射的情况下,通过Field.setAccessible(),在 JNI 的情况下 - 默认情况下。

    考虑到这一点,您可以在原生 FD 周围构造一个 FileDescriptor 就好了。构造一个空白,然后设置descriptor。这就是构建这些 Android 代码时的点点滴滴。

    这个肮脏的黑客最终会不会崩溃,谁知道呢。幸运的是,在我的例子中,它不是核心功能——有一些优雅的降级。

    如果平台允许,可以有条件地使用支持的ParcelFileDescriptor 方法,使用字段访问黑客作为后备。这样一来,它就会相对具有未来性。

    【讨论】:

      【解决方案2】:

      在帮助库 libnativehelper.so 中有一个方法用于这个 jniCreateFileDescriptor() https://android.googlesource.com/platform/libnativehelper/+/jb-dev/include/nativehelper/JNIHelp.h。它基本上与之前的答案中所述相同,但您可能会发现这种方法更简洁。

      【讨论】:

        【解决方案3】:

        这就是我在处理类似问题时的工作方式:

        我没有使用 shmfd = open(SHM_PATH, O_RDWR) 创建和获取文件描述符,而是将其替换为

        int fd = ashmem_create_region("SharedRegionName", size); 
        

        并使用文件描述符获取基地址:

        int base_address = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        

        //写入数据 您可以使用返回描述符的本机函数将 base_address 从本机代码传递给您的 java 代码。

        然后我创建了一个带有aidl接口的服务,并使用这个接口从另一个进程绑定了这个服务。从服务中,我使用 ParcelFileDescriptor 对象返回到另一个进程。您可以通过以下方式创建 ParcelFileDescriptor:

        ParcelFileDescriptor desc = ParcelFileDescriptor.fromFd(fd);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-24
          • 1970-01-01
          • 2012-10-31
          • 2013-08-30
          相关资源
          最近更新 更多