使用 Android NDK SharedMemory.h 进行多进程

Multiprocess by Using Android NDK SharedMemory.h

我一直在 Android Studio(使用 NDK)中尝试多处理(使用共享内存)。我安装了 NDK、LLDB、CMake。我还使用 API 级别 26,最小 SDK 也是 26(OREO,8.0)。

我创建了 native_lib.cpp,并制作了一些用于测试 FD 的文件。

我制作了简单的小class用于测试。

Class 有 int FileDescriptor, char* buffer.

我检查了变量,似乎已经成功了。 ASharedMemory_Create() returns fd,我可以从 ASharedMemory_getSize(int fd) 获取内存大小。

但是我怎样才能从另一个进程访问共享内存呢?我需要为 IPC 使用 java 吗?如果可以的话,我只想使用本机。目前 java 仅适用于 UI。

https://developer.android.com/ndk/reference/group/memory

我查到了这里。如果有值得我参考的东西,请告诉我。谢谢你。

已编辑------------------------------------ --------------

我想在 parent 和 child 中创建共享内存。也想自由访问共享内存。 Child 到 child,child 到 parents,parents 到 child。

在 parents 中创建文件描述符和缓冲区工作顺利,但是当我尝试在 child 中创建缓冲区或 fd 时,我无法访问它。

我为 ASharedMemory_create 使用了相同的名称和大小,但我认为其他进程生成不同的文件描述符。不知道怎么了。

下面是我的native_lib.cpp测试。除了 Init 之外,与 Buttons 匹配的功能。 InitonCreate.

int fd[4];
char* buffer[4];

int myFd;
int* cBuf;

const char* names[4] = {"Test", "Inter", "Process", "Mech"};
const int size = 512;

extern "C" JNIEXPORT void JNICALL
Java_org_techtwon_multipro_MainActivity_SyncBuffer(
        JNIEnv *env,
        jobject /* this */) {
    int cVal;
    memcpy(&cVal, cBuf, sizeof(int));

    for(int i = 0 ; i < cVal; ++i)
    {
        if(fd[i] != NULL) {
            buffer[i] = (char *) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[i], 0);
        }
    }
}

extern "C" JNIEXPORT void JNICALL
Java_org_techtwon_multipro_MainActivity_MakeFileDesc(
        JNIEnv *env,
        jobject /* this */) {

    pid_t pid = fork();
    int cVal;

    if(pid < 0) {
        return;
    } else if(pid == 0) {
        memcpy(&cVal, cBuf, sizeof(int));

        fd[cVal] = ASharedMemory_create(names[cVal], size);
        buffer[cVal] = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd[cVal], 0);

        memset(buffer[cVal], 0, size);
        memcpy(buffer[cVal], names[cVal], strlen(names[cVal]));

        cVal++;
        memcpy(cBuf, &cVal, sizeof(int));

        sleep(1);
        exit(1);
    }
}

extern "C" JNIEXPORT void JNICALL
Java_org_techtwon_multipro_MainActivity_Init(
        JNIEnv *env,
        jobject /* this */) {
    myFd = ASharedMemory_create("Num", sizeof(int));
    cBuf = (int*) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, myFd, 0);

    for(int i = 0 ; i < 4; ++i) fd[i] = ASharedMemory_create(names[i], size);

    buffer[0] = (char*) mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd[0], 0);
    memcpy(buffer[0], names[0], strlen(names[0]));

    memset(cBuf, 0, sizeof(int));
}

extern "C" JNIEXPORT jint JNICALL
Java_org_techtwon_multipro_MainActivity_GetFd(
        JNIEnv *env,
        jobject /* this */, jint idx) {
    return fd[idx];
}

extern "C" JNIEXPORT jbyteArray JNICALL
Java_org_techtwon_multipro_MainActivity_GetBuffer(
        JNIEnv *env,
        jobject /* this */, jint idx) {

    jbyteArray tmp = (*env).NewByteArray(strlen(buffer[idx]));

    env->SetByteArrayRegion(tmp, 0, strlen(buffer[idx]), (jbyte*) buffer[idx]);

    return tmp;
}

extern "C" JNIEXPORT jint JNICALL
Java_org_techtwon_multipro_MainActivity_GetcVal(
        JNIEnv *env,
        jobject /* this */, jint idx) {

    int cVal;
    memcpy(&cVal, cBuf, sizeof(int));

    return cVal;
}

official docs 中的代码片段非常清楚:

int fd = ASharedMemory_create("memory", 128);

// By default it has PROT_READ | PROT_WRITE | PROT_EXEC.
char *buffer = (char *) mmap(NULL, 128, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

strcpy(buffer, "This is an example."); // trivially initialize content

// limit access to read only
ASharedMemory_setProt(fd, PROT_READ);

// share fd with another process here and the other process can only map with PROT_READ.

name没有任何意义,只对调试有帮助。 尺寸应该匹配。

这就是API你 for API 29 and higher, the old ways (below) don't work anymore.

如果您还需要涵盖 API 26 以下的设备,您需要一个 fallback 将 IOCTL 直接指向 /dev/ashmem 文件描述符。这在 Android 早期就可用:

#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/ashmem.h>

int fd = open("/dev/ashmem", O_RDWR);

ioctl(fd, ASHMEM_SET_NAME, "memory");
ioctl(fd, ASHMEM_SET_SIZE, 128);

char *buffer = (char * ) mmap(NULL, 128, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

甚至还有一个包装此共享内存以供在 Java 中使用的好示例:ANDROID – CREATING SHARED MEMORY USING ASHMEM.