1

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

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

或者,我可以创建一个MemoryFile. 在 Parcels 中传递它有一种丑陋的方式。但是我如何从中检索文件描述符,以便本机代码有一些东西mmap()呢?

4

3 回答 3

3

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

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

谁知道这个肮脏的黑客最终是否会破裂。幸运的是,在我的例子中,它不是核心功能——有一些优雅的退化。

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

于 2012-10-12T21:43:15.313 回答
3

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

于 2013-06-24T15:32:02.587 回答
0

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

我没有使用 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);
于 2013-09-23T18:43:19.873 回答