安卓开启Sys V IPC,并使用共享内存编程

发布于 2023-08-22  355 次阅读


一、安卓开启Sys V IPC

1.1 配置kernel

为了在安卓下使用shm,我们需要开启Sys V IPC功能,首先我们需要开启kernel的general -> Sys V IPC

1.2 修改domain.te

之后我们将./system/sepolicy/public/domain.te中的neverallow * *:{ shm sem msg msgq } *;修改为neverallow * *:{ sem msg msgq } *;。这里根据需要移除对应的IPC选型,在编译时我遇到了报错,提示还需要保持./system/sepolicy/prebuilts/api/30/public/domain.te和上述文件一致。

1.3 修改check_vintf.cpp

安卓编译的时候还会有一个检查,以确保CONFIG_SYS_V_IPC设置为n,为了规避这项检查,我们需要修改./system/libvintf/check_vintf.cpp中的代码:

    if (compat.ok()) {
        std::cout << "COMPATIBLE" << std::endl;
        return EX_OK;
    }
    if (compat.error().code() == 0) {
        LOG(ERROR) << "files are incompatible: " << compat.error();
        std::cout << "INCOMPATIBLE" << std::endl;
        // return EX_DATAERR;
        return EX_OK;
    }
    LOG(ERROR) << strerror(compat.error().code()) << ": " << compat.error();
    return EX_SOFTWARE;

这里我们将return EX_DATAERR;修改为return EX_OK;,但是在修改的时候需要确保你的系统没有其他错误。建议先正常编译后,再开启Sys V IPC功能。

二、使用共享内存通信

2.1 发送进程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() 
{
    int shmid;
    char *shmaddr;
    char message[] = "hello world";

    key_t key1 = ftok("/data/local/tmp/key/test_key", 1);

    // 创建共享内存段
    shmid = shmget(key1, sizeof(message), IPC_CREAT | 0666);
    if (shmid == -1) {
        perror("shmget");
        exit(1);
    }

    // 将共享内存连接到当前进程的地址空间
    shmaddr = (char *)shmat(shmid, NULL, 0);
    if (shmaddr == (char *)(-1)) {
        perror("shmat");
        exit(1);
    }

    // 将数据写入共享内存
    strcpy(shmaddr, message);

    printf("Message '%s' written to shared memory\n", message);

    // 分离共享内存
    shmdt(shmaddr);

    return 0;
}

2.2 接收进程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    int shmid;
    char *shmaddr;

    key_t key1 = ftok("/data/local/tmp/key/test_key", 1);

    // 获取共享内存段 12 is sizeof("hello world")
    shmid = shmget(key1, 12, 0666);
    if (shmid == -1) {
        perror("shmget");
        exit(1);
    }

    // 连接到共享内存段
    shmaddr = (char *)shmat(shmid, NULL, 0);
    if (shmaddr == (char *)(-1)) {
        perror("shmat");
        exit(1);
    }

    // 从共享内存读取数据并打印
    printf("Read from shared memory: %s\n", shmaddr);

    // 分离共享内存
    shmdt(shmaddr);

    // 删除共享内存段(在实际应用中,可能需要谨慎处理删除操作)
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}