繁体   English   中英

NDK中的共享内存区域

[英]Shared memory region in NDK

我想要一个共享内存块(一个ashmem区域),该内存块是从本机代码映射和访问的。 我也希望该块可以被多个应用程序使用。 我也希望它能在SDK级别7(Android 2.1)上运行

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

另外,我可以创建一个MemoryFile 有一种在包裹中传递它的丑陋方法 但是,如何从文件描述符中检索文件描述符,以便本机代码具有mmap()

在从1.5到4.1的所有版本的Android上, FileDescriptor都有一个称为descriptorint数据成员。 它在较早版本的Android上是私有包,在最近的Android上是私有包。 通过一些故意的访问控制颠覆,您可以通过反射或JNI进行访问。 默认情况下,每个用户都可以绕过访问控制(如果发生反射,则通过Field.setAccessible() ;如果是JNI,则可以Field.setAccessible()

考虑到这一点,您可以很好地围绕本机FD构造FileDescriptor 构造一个空白的,然后设置descriptor 这就是构造这些代码时会执行的零碎工作。

谁知道,这个肮脏的hack最终是否会破裂。 幸运的是,在我看来,这并不是核心功能,而是有些优雅的降级。

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

辅助程序库libnativehelper.so中有一个用于此jniCreateFileDescriptor() https://android.googlesource.com/platform/libnativehelper/+/jb-dev/include/nativehelper/JNIHelp.h的方法 它基本上执行与先前答案中所述相同的操作,但是您可能会发现此方法更简洁。

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

与其使用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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM